fix(multi-tool): refactor fileInput.js into a class, fix filename variable typos, and update updateFilename logic for dropping files

This commit is contained in:
sbplat 2024-01-18 01:08:31 -05:00
parent 1bd17eded6
commit a5165b04cd
5 changed files with 100 additions and 100 deletions

View file

@ -115,4 +115,4 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
return false;
}
}
}

View file

@ -121,8 +121,8 @@ public class SplitPdfBySectionsController {
subDoc, subPage, AppendMode.APPEND, true, true)) {
// Set clipping area and position
float translateX = -subPageWidth * i;
//float translateY = height - subPageHeight * (verticalDivisions - j);
// float translateY = height - subPageHeight * (verticalDivisions - j);
float translateY = -subPageHeight * (verticalDivisions - 1 - j);
contentStream.saveGraphicsState();

View file

@ -26,6 +26,7 @@ class PdfContainer {
movePageTo: this.movePageTo,
addPdfs: this.addPdfs,
rotateElement: this.rotateElement,
updateFilename: this.updateFilename
})
})
@ -38,7 +39,7 @@ class PdfContainer {
filenameInput.onkeyup = this.updateFilename;
filenameInput.onkeydown = this.preventIllegalChars;
filenameInput.disabled = true;
filenameInput.disabled = false;
filenameInput.innerText = "";
downloadBtn.disabled = true;
}
@ -59,7 +60,7 @@ class PdfContainer {
const vector = (endIndex !== -1 && startIndex > endIndex)
? 0-width
: width;
this.pagesContainerWrapper.scroll({
left: this.pagesContainerWrapper.scrollLeft + vector,
})
@ -73,38 +74,14 @@ class PdfContainer {
input.setAttribute("accept", "application/pdf");
input.onchange = async(e) => {
const files = e.target.files;
if (files.length > 0) {
updateFilenameInput()
}
this.addPdfsFromFiles(files, nextSiblingElement);
this.updateFilename(files ? files[0].name : "");
}
input.click();
}
updateFilenameInput() {
const filenameInput = document.getElementById('filename-input');
const pagesContainer = document.getElementById('pages-container');
const downloadBtn = document.getElementById('export-button');
filenameInput.disabled = false;
if (pagesContainer.childElementCount === 0) {
filenameInput.value = "";
this.filename = null;
downloadBtn.disabled = true;
} else {
this.filename = filenameInput.value;
}
if (this.filename === null || this.filename === undefined) {
filenameInput.value = files[0].name;
} else {
filenameInput.value = this.filename;
}
}
async addPdfsFromFiles(files, nextSiblingElement) {
this.fileName = files[0].name;
for (var i=0; i < files.length; i++) {
@ -200,7 +177,7 @@ class PdfContainer {
return pdfDoc;
}
rotateAll(deg) {
for (var i=0; i<this.pagesContainer.childNodes.length; i++) {
@ -218,13 +195,13 @@ class PdfContainer {
if (!img) continue;
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
const page = pages[0];
const rotation = img.style.rotate;
if (rotation) {
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
}
pdfDoc.addPage(page);
}
const pdfBytes = await pdfDoc.save();
@ -245,12 +222,12 @@ class PdfContainer {
}
filenameInput.value = inputArr.join('');
this.filename = filenameInput.value;
this.fileName = filenameInput.value;
}
if (!filenameInput.value.includes('.pdf')) {
filenameInput.value = filenameInput.value + '.pdf';
this.filename = filenameInput.value;
this.fileName = filenameInput.value;
}
if (downloadOption === 'sameWindow') {
@ -266,7 +243,7 @@ class PdfContainer {
this.downloadLink.href = url;
// downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
// downloadLink.download = this.fileName;
this.downloadLink.setAttribute('download', this.filename ? this.fileName : 'managed.pdf');
this.downloadLink.setAttribute('download', this.fileName ? this.fileName : 'managed.pdf');
this.downloadLink.setAttribute('target', '_blank');
this.downloadLink.onclick = this.setDownloadAttribute;
this.downloadLink.click();
@ -274,20 +251,23 @@ class PdfContainer {
}
setDownloadAttribute() {
this.downloadLink.setAttribute("download", this.filename ? this.filename : 'managed.pdf');
this.downloadLink.setAttribute("download", this.fileName ? this.fileName : 'managed.pdf');
}
updateFilename() {
updateFilename(fileName = "") {
const filenameInput = document.getElementById('filename-input');
const pagesContainer = document.getElementById('pages-container');
const downloadBtn = document.getElementById('export-button');
if (filenameInput.value === "") {
downloadBtn.disabled = true;
return;
downloadBtn.disabled = pagesContainer.childElementCount === 0
if (!this.fileName) {
this.fileName = fileName;
}
downloadBtn.disabled = false;
this.filename = filenameInput.value;
if (!filenameInput.value) {
filenameInput.value = this.fileName;
}
}
preventIllegalChars(e) {

View file

@ -1,75 +1,94 @@
import PdfContainer from "./PdfContainer";
class FileDragManager {
overlay;
dragCounter;
updateFilename;
const addFileDragListener = (callback) => {
let overlay;
let dragCounter = 0;
constructor(cb = null) {
this.dragCounter = 0;
this.setCallback(cb);
const dragenterListener = function() {
dragCounter++;
if (!overlay) {
// Prevent default behavior for drag events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
document.body.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
this.dragenterListener = this.dragenterListener.bind(this);
this.dragleaveListener = this.dragleaveListener.bind(this);
this.dropListener = this.dropListener.bind(this);
document.body.addEventListener('dragenter', this.dragenterListener);
document.body.addEventListener('dragleave', this.dragleaveListener);
// Add drop event listener
document.body.addEventListener('drop', this.dropListener);
}
setActions({ updateFilename }) {
this.updateFilename = updateFilename;
}
setCallback(cb) {
if (cb) {
this.callback = cb;
} else {
this.callback = (files) => console.warn("FileDragManager not set");
}
}
dragenterListener() {
this.dragCounter++;
if (!this.overlay) {
// Create and show the overlay
overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.top = 0;
overlay.style.left = 0;
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.background = 'rgba(0, 0, 0, 0.5)';
overlay.style.color = '#fff';
overlay.style.zIndex = '1000';
overlay.style.display = 'flex';
overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center';
overlay.style.pointerEvents = 'none';
overlay.innerHTML = '<p>Drop files anywhere to upload</p>';
document.getElementById('content-wrap').appendChild(overlay);
this.overlay = document.createElement('div');
this.overlay.style.position = 'fixed';
this.overlay.style.top = 0;
this.overlay.style.left = 0;
this.overlay.style.width = '100%';
this.overlay.style.height = '100%';
this.overlay.style.background = 'rgba(0, 0, 0, 0.5)';
this.overlay.style.color = '#fff';
this.overlay.style.zIndex = '1000';
this.overlay.style.display = 'flex';
this.overlay.style.alignItems = 'center';
this.overlay.style.justifyContent = 'center';
this.overlay.style.pointerEvents = 'none';
this.overlay.innerHTML = '<p>Drop files anywhere to upload</p>';
document.getElementById('content-wrap').appendChild(this.overlay);
}
};
const dragleaveListener = function() {
dragCounter--;
if (dragCounter === 0) {
dragleaveListener() {
this.dragCounter--;
if (this.dragCounter === 0) {
// Hide and remove the overlay
if (overlay) {
overlay.remove();
overlay = null;
if (this.overlay) {
this.overlay.remove();
this.overlay = null;
}
}
};
const dropListener = function(e) {
dropListener(e) {
const dt = e.dataTransfer;
const files = dt.files;
callback(files).catch((err) => {
this.callback(files).catch((err) => {
console.error(err);
//maybe
}).finally(() => {
// Hide and remove the overlay
if (overlay) {
overlay.remove();
overlay = null;
if (this.overlay) {
this.overlay.remove();
this.overlay = null;
}
// Enable/disable filename input
PdfContainer.updateFilenameInput()
this.updateFilename(files ? files[0].name : "");
});
};
// Prevent default behavior for drag events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
document.body.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
document.body.addEventListener('dragenter', dragenterListener);
document.body.addEventListener('dragleave', dragleaveListener);
// Add drop event listener
document.body.addEventListener('drop', dropListener);
}
export default addFileDragListener;
export default FileDragManager;

View file

@ -49,7 +49,7 @@
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
</svg>
</button>
<button class="btn btn-secondary enable-on-file" onclick="rotateAll(90)" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
@ -79,13 +79,14 @@
import scrollDivHorizontally from "./js/multitool/horizontalScroll.js";
import ImageHighlighter from "./js/multitool/ImageHighlighter.js";
import PdfActionsManager from './js/multitool/PdfActionsManager.js';
import addFileInputListener from './js/multitool/fileInput.js';
import FileDragManager from './js/multitool/fileInput.js';
// enables drag and drop
const dragDropManager = new DragDropManager('drag-container', 'pages-container');
// enables image highlight on click
const imageHighlighter = new ImageHighlighter('image-highlighter');
// enables the default action buttons on each pdf
const pdfActionsManager = new PdfActionsManager('pages-container');
const fileDragManager = new FileDragManager();
// Scroll the wrapper horizontally
scrollDivHorizontally('pages-container-wrapper');
@ -98,11 +99,11 @@
dragDropManager,
imageHighlighter,
pdfActionsManager,
fileDragManager
]
)
addFileInputListener(async (files) => {
pdfContainer.addPdfsFromFiles(files);
});
fileDragManager.setCallback(async (files) => pdfContainer.addPdfsFromFiles(files));
</script>
<style>
@ -186,7 +187,7 @@
.page-container {
height:250px;
display: flex;
display: flex;
align-items: center;
flex-direction: column-reverse;
aspect-ratio: 1;