diff --git a/src/main/resources/static/js/multitool/dragDrop.js b/src/main/resources/static/js/multitool/DragDropManager.js
similarity index 88%
rename from src/main/resources/static/js/multitool/dragDrop.js
rename to src/main/resources/static/js/multitool/DragDropManager.js
index 7a1066fd..90354551 100644
--- a/src/main/resources/static/js/multitool/dragDrop.js
+++ b/src/main/resources/static/js/multitool/DragDropManager.js
@@ -8,9 +8,8 @@ class DragDropManager {
draggedImageEl;
hoveredEl;
- constructor(id, movePageTo) {
+ constructor(id) {
this.dragContainer = document.getElementById(id);
- this.movePageTo = movePageTo;
this.pageDragging = false;
this.hoveredEl = undefined;
this.draggelEl = undefined
@@ -19,8 +18,6 @@ class DragDropManager {
this.startDraggingPage = this.startDraggingPage.bind(this);
this.onDragEl = this.onDragEl.bind(this);
this.stopDraggingPage = this.stopDraggingPage.bind(this);
- this.attachDragDropCallbacks = this.attachDragDropCallbacks.bind(this);
-
}
startDraggingPage(div, imageSrc) {
@@ -34,9 +31,7 @@ class DragDropManager {
this.draggedImageEl.style.left = screenX;
this.draggedImageEl.style.right = screenY;
this.dragContainer.appendChild(imgEl);
- window.addEventListener('mouseup', (e) => {
- this.stopDraggingPage();
- })
+ window.addEventListener('mouseup', this.stopDraggingPage)
window.addEventListener('mousemove', this.onDragEl)
}
@@ -51,6 +46,7 @@ class DragDropManager {
stopDraggingPage() {
window.removeEventListener('mousemove', this.onDragEl);
+ window.removeEventListener('mouseup', this.stopDraggingPage)
this.draggedImageEl = undefined;
this.pageDragging = false;
this.draggedEl.classList.remove('dragging');
@@ -61,10 +57,14 @@ class DragDropManager {
this.movePageTo(this.draggedEl, this.hoveredEl);
}
+ setActions({ movePageTo }) {
+ this.movePageTo = movePageTo;
+ }
- attachDragDropCallbacks(div, imageSrc) {
+
+ adapt(div) {
const onDragStart = () => {
- this.startDraggingPage(div, imageSrc);
+ this.startDraggingPage(div, div.querySelector('img').src);
}
const onMouseEnter = () => {
@@ -82,6 +82,8 @@ class DragDropManager {
div.addEventListener('dragstart', onDragStart);
div.addEventListener('mouseenter', onMouseEnter);
div.addEventListener('mouseleave', onMouseLeave);
+
+ return div;
}
}
diff --git a/src/main/resources/static/js/multitool/pdfActions.js b/src/main/resources/static/js/multitool/PdfActionsManager.js
similarity index 66%
rename from src/main/resources/static/js/multitool/pdfActions.js
rename to src/main/resources/static/js/multitool/PdfActionsManager.js
index 14bfc349..b716f1d1 100644
--- a/src/main/resources/static/js/multitool/pdfActions.js
+++ b/src/main/resources/static/js/multitool/PdfActionsManager.js
@@ -1,73 +1,75 @@
class PdfActionsManager {
- callbacks;
- pageDirection;
- constructor(id, { movePageTo, addPdfs, rotateElement }) {
- this.pageDirection = document.documentElement.getAttribute("lang-direction");
- const moveUpButtonCallback = e => {
- var imgContainer = e.target;
- while (!imgContainer.classList.contains(id)) {
- imgContainer = imgContainer.parentNode;
- }
-
- const sibling = imgContainer.previousSibling;
- if (sibling) {
- movePageTo(imgContainer, sibling, true);
- }
- };
- const moveDownButtonCallback = e => {
- var imgContainer = e.target;
- while (!imgContainer.classList.contains(id)) {
- imgContainer = imgContainer.parentNode;
- }
- const sibling = imgContainer.nextSibling;
- if (sibling) {
- movePageTo(imgContainer, sibling.nextSibling, true);
- }
- };
- const rotateCCWButtonCallback = e => {
- var imgContainer = e.target;
- while (!imgContainer.classList.contains(id)) {
- imgContainer = imgContainer.parentNode;
- }
- const img = imgContainer.querySelector("img");
-
- rotateElement(img, -90)
- };
- const rotateCWButtonCallback = e => {
- var imgContainer = e.target;
- while (!imgContainer.classList.contains(id)) {
- imgContainer = imgContainer.parentNode;
- }
- const img = imgContainer.querySelector("img");
-
- rotateElement(img, 90)
- };
- const deletePageButtonCallback = e => {
- var imgContainer = e.target;
- while (!imgContainer.classList.contains(id)) {
- imgContainer = imgContainer.parentNode;
- }
- pagesContainer.removeChild(imgContainer);
- };
- const insertFileButtonCallback = e => {
- var imgContainer = e.target;
- while (!imgContainer.classList.contains(id)) {
- imgContainer = imgContainer.parentNode;
- }
- addPdfs(imgContainer)
- };
+ pageDirection;
+ pagesContainer;
- this.callbacks = {
- moveUpButtonCallback,
- moveDownButtonCallback,
- rotateCCWButtonCallback,
- rotateCWButtonCallback,
- deletePageButtonCallback,
- insertFileButtonCallback
+ constructor(id) {
+ this.pagesContainer = document.getElementById(id);
+ this.pageDirection = document.documentElement.getAttribute("lang-direction");
+ }
+
+ getPageContainer(element) {
+ var container = element
+ while (!container.classList.contains('page-container')) {
+ container = container.parentNode;
+ }
+ return container;
+ }
+
+ moveUpButtonCallback(e) {
+ var imgContainer = this.getPageContainer(e.target);
+
+ const sibling = imgContainer.previousSibling;
+ if (sibling) {
+ this.movePageTo(imgContainer, sibling, true);
}
}
- attachPDFActions(div) {
+ moveDownButtonCallback(e) {
+ var imgContainer = this.getPageContainer(e.target);
+ const sibling = imgContainer.nextSibling;
+ if (sibling) {
+ this.movePageTo(imgContainer, sibling.nextSibling, true);
+ }
+ };
+
+ rotateCCWButtonCallback(e) {
+ var imgContainer = this.getPageContainer(e.target);
+ const img = imgContainer.querySelector("img");
+
+ this.rotateElement(img, -90)
+ };
+
+ rotateCWButtonCallback(e) {
+ var imgContainer = this.getPageContainer(e.target);
+ const img = imgContainer.querySelector("img");
+
+ this.rotateElement(img, 90)
+ };
+
+ deletePageButtonCallback(e) {
+ var imgContainer = this.getPageContainer(e.target);
+ this.pagesContainer.removeChild(imgContainer);
+ };
+
+ insertFileButtonCallback(e) {
+ var imgContainer = this.getPageContainer(e.target);
+ this.addPdfs(imgContainer)
+ };
+
+ setActions({ movePageTo, addPdfs, rotateElement }) {
+ this.movePageTo = movePageTo;
+ this.addPdfs = addPdfs;
+ this.rotateElement = rotateElement;
+
+ this.moveUpButtonCallback = this.moveUpButtonCallback.bind(this);
+ this.moveDownButtonCallback = this.moveDownButtonCallback.bind(this);
+ this.rotateCCWButtonCallback = this.rotateCCWButtonCallback.bind(this);
+ this.rotateCWButtonCallback = this.rotateCWButtonCallback.bind(this);
+ this.deletePageButtonCallback = this.deletePageButtonCallback.bind(this);
+ this.insertFileButtonCallback = this.insertFileButtonCallback.bind(this);
+ }
+
+ adapt(div) {
const leftDirection = this.pageDirection === 'rtl' ? 'right' : 'left'
const rightDirection = this.pageDirection === 'rtl' ? 'left' : 'right'
const buttonContainer = document.createElement('div');
@@ -77,13 +79,13 @@ class PdfActionsManager {
const moveUp = document.createElement('button');
moveUp.classList.add("move-left-button","btn", "btn-secondary");
moveUp.innerHTML = ``;
- moveUp.onclick = this.callbacks.moveUpButtonCallback;
+ moveUp.onclick = this.moveUpButtonCallback;
buttonContainer.appendChild(moveUp);
const moveDown = document.createElement('button');
moveDown.classList.add("move-right-button","btn", "btn-secondary");
moveDown.innerHTML = ``;
- moveDown.onclick = this.callbacks.moveDownButtonCallback;
+ moveDown.onclick = this.moveDownButtonCallback;
buttonContainer.appendChild(moveDown);
const rotateCCW = document.createElement('button');
@@ -92,7 +94,7 @@ class PdfActionsManager {
`;
- rotateCCW.onclick = this.callbacks.rotateCCWButtonCallback;
+ rotateCCW.onclick = this.rotateCCWButtonCallback;
buttonContainer.appendChild(rotateCCW);
const rotateCW = document.createElement('button');
@@ -101,7 +103,7 @@ class PdfActionsManager {
`;
- rotateCW.onclick = this.callbacks.rotateCWButtonCallback;
+ rotateCW.onclick = this.rotateCWButtonCallback;
buttonContainer.appendChild(rotateCW);
const deletePage = document.createElement('button');
@@ -110,7 +112,7 @@ class PdfActionsManager {
`;
- deletePage.onclick = this.callbacks.deletePageButtonCallback;
+ deletePage.onclick = this.deletePageButtonCallback;
buttonContainer.appendChild(deletePage);
div.appendChild(buttonContainer);
@@ -128,7 +130,7 @@ class PdfActionsManager {
`;
- insertFileButton.onclick = this.callbacks.insertFileButtonCallback;
+ insertFileButton.onclick = this.insertFileButtonCallback;
insertFileButtonContainer.appendChild(insertFileButton);
div.appendChild(insertFileButtonContainer);
@@ -150,6 +152,8 @@ class PdfActionsManager {
insertFileButtonRightContainer.appendChild(insertFileButtonRight);
div.appendChild(insertFileButtonRightContainer);
+
+ return div;
}
}
diff --git a/src/main/resources/static/js/multitool/horizontalScroll.js b/src/main/resources/static/js/multitool/horizontalScroll.js
index c1c5ca87..2d20ee79 100644
--- a/src/main/resources/static/js/multitool/horizontalScroll.js
+++ b/src/main/resources/static/js/multitool/horizontalScroll.js
@@ -1,12 +1,10 @@
-
-
const scrollDivHorizontally = (id) => {
var scrollDelta = 0; // variable to store the accumulated scroll delta
var isScrolling = false; // variable to track if scroll is already in progress
- const pagesContainerWrapper = document.getElementById(id);
+ const divToScrollHorizontally = document.getElementById(id)
function scrollLoop() {
// Scroll the div horizontally by a fraction of the accumulated scroll delta
- pagesContainerWrapper.scrollLeft += scrollDelta * 0.1;
+ divToScrollHorizontally.scrollLeft += scrollDelta * 0.1;
// Reduce the accumulated scroll delta by a fraction
scrollDelta *= 0.9;
@@ -19,7 +17,7 @@ const scrollDivHorizontally = (id) => {
}
}
- const divToScrollHorizontally = document.getElementById(id)
+
divToScrollHorizontally.addEventListener("wheel", function(e) {
e.preventDefault(); // prevent default mousewheel behavior
diff --git a/src/main/resources/static/js/multitool/imageHighlighter.js b/src/main/resources/static/js/multitool/imageHighlighter.js
index 15f54c98..d20510d3 100644
--- a/src/main/resources/static/js/multitool/imageHighlighter.js
+++ b/src/main/resources/static/js/multitool/imageHighlighter.js
@@ -1,27 +1,39 @@
-const getImageHighlighterCallback = (id) => {
- const imageHighlighter = document.getElementById(id);
- imageHighlighter.onclick = () => {
- imageHighlighter.childNodes.forEach((child) => {
- child.classList.add('remove');
- setTimeout(() => {
- imageHighlighter.removeChild(child);
- }, 100)
- })
+class ImageHiglighter {
+ imageHighlighter;
+ constructor(id) {
+ this.imageHighlighter = document.getElementById(id);
+ this.imageHighlightCallback = this.imageHighlightCallback.bind(this);
+ this.imageHighlighter.onclick = () => {
+ this.imageHighlighter.childNodes.forEach((child) => {
+ child.classList.add('remove');
+ setTimeout(() => {
+ this.imageHighlighter.removeChild(child);
+ }, 100)
+ })
+ }
}
- const imageHighlightCallback = (highlightEvent) => {
+ imageHighlightCallback(highlightEvent) {
var bigImg = document.createElement('img');
bigImg.onclick = (imageClickEvent) => {
- // This prevents the highlighter's onClick from closing the image when clicking on the image
- // instead of next to it.
+ // This prevents the highlighter's onClick from closing the image when clicking
+ // on the image instead of next to it.
imageClickEvent.preventDefault();
imageClickEvent.stopPropagation();
};
bigImg.src = highlightEvent.target.src;
- imageHighlighter.appendChild(bigImg);
+ this.imageHighlighter.appendChild(bigImg);
};
- return imageHighlightCallback
+ setActions() {
+ // not needed in this case
+ }
+
+ adapt(div) {
+ const img = div.querySelector('.page-image');
+ img.addEventListener('click', this.imageHighlightCallback)
+ return div;
+ }
}
-export default getImageHighlighterCallback;
\ No newline at end of file
+export default ImageHiglighter;
\ No newline at end of file
diff --git a/src/main/resources/static/js/multitool/pdfContainer.js b/src/main/resources/static/js/multitool/pdfContainer.js
index 64c5efa4..f1cc1061 100644
--- a/src/main/resources/static/js/multitool/pdfContainer.js
+++ b/src/main/resources/static/js/multitool/pdfContainer.js
@@ -1,23 +1,43 @@
-import DragDropManager from "./dragDrop.js";
-import scrollDivHorizontally from "./horizontalScroll.js";
-import getImageHighlighterCallback from "./imageHighlighter.js";
-import PdfActionsManager from './pdfActions.js';
+class PdfContainer {
+ fileName;
+ pagesContainer;
+ pagesContainerWrapper;
+ pdfAdapters;
-const createPdfContainer = (id, wrapperId, highlighterId, dragElId) => {
- var fileName = null;
- const pagesContainer = document.getElementById(id);
- const pagesContainerWrapper = document.getElementById(wrapperId);
+ constructor(id, wrapperId, pdfAdapters) {
+ this.fileName = null;
+ this.pagesContainer = document.getElementById(id)
+ this.pagesContainerWrapper = document.getElementById(wrapperId);
+ this.movePageTo = this.movePageTo.bind(this);
+ this.addPdfs = this.addPdfs.bind(this);
+ this.rotateElement = this.rotateElement.bind(this);
+ this.rotateAll = this.rotateAll.bind(this);
+ this.exportPdf = this.exportPdf.bind(this);
+ this.pdfAdapters = pdfAdapters;
- const movePageTo = (startElement, endElement, scrollTo = false) => {
- const childArray = Array.from(pagesContainer.childNodes);
+ this.pdfAdapters.forEach(adapter => {
+ adapter.setActions({
+ movePageTo: this.movePageTo,
+ addPdfs: this.addPdfs,
+ rotateElement: this.rotateElement,
+ })
+ })
+
+ window.addPdfs = this.addPdfs;
+ window.exportPdf = this.exportPdf;
+ window.rotateAll = this.rotateAll;
+ }
+
+ movePageTo(startElement, endElement, scrollTo = false) {
+ const childArray = Array.from(this.pagesContainer.childNodes);
const startIndex = childArray.indexOf(startElement);
const endIndex = childArray.indexOf(endElement);
- pagesContainer.removeChild(startElement);
+ this.pagesContainer.removeChild(startElement);
if(!endElement) {
- pagesContainer.append(startElement);
+ this.pagesContainer.append(startElement);
} else {
- pagesContainer.insertBefore(startElement, endElement);
+ this.pagesContainer.insertBefore(startElement, endElement);
}
if(scrollTo) {
@@ -26,13 +46,13 @@ const createPdfContainer = (id, wrapperId, highlighterId, dragElId) => {
? 0-width
: width;
- pagesContainerWrapper.scroll({
- left: pagesContainerWrapper.scrollLeft + vector,
+ this.pagesContainerWrapper.scroll({
+ left: this.pagesContainerWrapper.scrollLeft + vector,
})
}
}
- function addPdfs(nextSiblingElement) {
+ addPdfs(nextSiblingElement) {
var input = document.createElement('input');
input.type = 'file';
input.multiple = true;
@@ -40,9 +60,9 @@ const createPdfContainer = (id, wrapperId, highlighterId, dragElId) => {
input.onchange = async(e) => {
const files = e.target.files;
- fileName = files[0].name;
+ this.fileName = files[0].name;
for (var i=0; i < files.length; i++) {
- addPdfFile(files[i], nextSiblingElement);
+ this.addPdfFile(files[i], nextSiblingElement);
}
document.querySelectorAll(".enable-on-file").forEach(element => {
@@ -53,7 +73,7 @@ const createPdfContainer = (id, wrapperId, highlighterId, dragElId) => {
input.click();
}
- function rotateElement(element, deg) {
+ rotateElement(element, deg) {
var lastTransform = element.style.rotate;
if (!lastTransform) {
lastTransform = "0";
@@ -63,22 +83,9 @@ const createPdfContainer = (id, wrapperId, highlighterId, dragElId) => {
element.style.rotate = newAngle + "deg";
}
-
- scrollDivHorizontally(wrapperId);
- var imageHighlighterCallback;
- if (highlighterId) {
- imageHighlighterCallback = getImageHighlighterCallback(highlighterId);
- }
- var dragDropManager;
- if(dragElId) {
- dragDropManager = new DragDropManager('drag-container', movePageTo);
- }
-
- var pdfActionManager = new PdfActionsManager('page-container', { movePageTo, addPdfs, rotateElement });
-
- async function addPdfFile(file, nextSiblingElement) {
- const { renderer, pdfDocument } = await loadFile(file);
+ async addPdfFile(file, nextSiblingElement) {
+ const { renderer, pdfDocument } = await this.loadFile(file);
for (var i=0; i < renderer.pageCount; i++) {
const div = document.createElement('div');
@@ -94,32 +101,25 @@ const createPdfContainer = (id, wrapperId, highlighterId, dragElId) => {
img.doc = pdfDocument;
div.appendChild(img);
-
- if(dragDropManager) {
- dragDropManager.attachDragDropCallbacks(div, imageSrc);
- }
-
- /**
- * Making pages larger when clicking on them
- */
- if(imageHighlighterCallback) {
- img.addEventListener('click', imageHighlighterCallback)
- }
-
- /**
- * Rendering the various buttons to manipulate and move pdf pages
- */
- pdfActionManager.attachPDFActions(div);
-
+ this.pdfAdapters.forEach((adapter) => {
+ adapter.adapt?.(div)
+ })
if (nextSiblingElement) {
- pagesContainer.insertBefore(div, nextSiblingElement);
+ this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
- pagesContainer.appendChild(div);
+ this.pagesContainer.appendChild(div);
}
}
}
- async function toRenderer(objectUrl) {
+ async loadFile(file) {
+ var objectUrl = URL.createObjectURL(file);
+ var pdfDocument = await this.toPdfLib(objectUrl);
+ var renderer = await this.toRenderer(objectUrl);
+ return { renderer, pdfDocument };
+ }
+
+ async toRenderer(objectUrl) {
const pdf = await pdfjsLib.getDocument(objectUrl).promise;
return {
document: pdf,
@@ -150,31 +150,26 @@ const createPdfContainer = (id, wrapperId, highlighterId, dragElId) => {
};
}
- async function toPdfLib(objectUrl) {
+ async toPdfLib(objectUrl) {
const existingPdfBytes = await fetch(objectUrl).then(res => res.arrayBuffer());
const pdfDoc = await PDFLib.PDFDocument.load(existingPdfBytes);
return pdfDoc;
}
- async function loadFile(file) {
- var objectUrl = URL.createObjectURL(file);
- var pdfDocument = await toPdfLib(objectUrl);
- var renderer = await toRenderer(objectUrl);
- return { renderer, pdfDocument };
- }
+
- function rotateAll(deg) {
- for (var i=0; i {
// Download the file
const downloadLink = document.createElement('a');
downloadLink.href = url;
- downloadLink.download = fileName ? fileName : 'managed.pdf';
+ downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
downloadLink.click();
}
}
-
- return {
- addPdfs,
- rotateAll,
- exportPdf,
- }
}
-export default createPdfContainer;
+export default PdfContainer;
diff --git a/src/main/resources/templates/multi-tool.html b/src/main/resources/templates/multi-tool.html
index ef8900c3..6f3ea682 100644
--- a/src/main/resources/templates/multi-tool.html
+++ b/src/main/resources/templates/multi-tool.html
@@ -52,7 +52,6 @@
-
@@ -61,20 +60,32 @@