Skip to content

Commit

Permalink
Add image support to multi-tool page
Browse files Browse the repository at this point in the history
Related to #278
  • Loading branch information
Frooodle committed Aug 28, 2024
1 parent 3160214 commit 1006927
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 19 deletions.
23 changes: 21 additions & 2 deletions src/main/resources/static/js/multitool/ImageHighlighter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class ImageHiglighter {
class ImageHighlighter {
imageHighlighter;
constructor(id) {
this.imageHighlighter = document.getElementById(id);
Expand Down Expand Up @@ -41,6 +41,25 @@ class ImageHiglighter {
img.addEventListener("click", this.imageHighlightCallback);
return div;
}

async addImageFile(file, nextSiblingElement) {
const div = document.createElement("div");
div.classList.add("page-container");

var img = document.createElement("img");
img.classList.add("page-image");
img.src = URL.createObjectURL(file);
div.appendChild(img);

this.pdfAdapters.forEach((adapter) => {
adapter.adapt?.(div);
});
if (nextSiblingElement) {
this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
this.pagesContainer.appendChild(div);
}
}
}

export default ImageHiglighter;
export default ImageHighlighter;
58 changes: 48 additions & 10 deletions src/main/resources/static/js/multitool/PdfContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class PdfContainer {
this.updateFilename = this.updateFilename.bind(this);
this.setDownloadAttribute = this.setDownloadAttribute.bind(this);
this.preventIllegalChars = this.preventIllegalChars.bind(this);
this.addImageFile = this.addImageFile.bind(this);

this.pdfAdapters = pdfAdapters;

Expand Down Expand Up @@ -69,7 +70,7 @@ class PdfContainer {
var input = document.createElement("input");
input.type = "file";
input.multiple = true;
input.setAttribute("accept", "application/pdf");
input.setAttribute("accept", "application/pdf,image/*");
input.onchange = async (e) => {
const files = e.target.files;

Expand All @@ -83,7 +84,12 @@ class PdfContainer {
async addPdfsFromFiles(files, nextSiblingElement) {
this.fileName = files[0].name;
for (var i = 0; i < files.length; i++) {
await this.addPdfFile(files[i], nextSiblingElement);
const file = files[i];
if (file.type === "application/pdf") {
await this.addPdfFile(file, nextSiblingElement);
} else if (file.type.startsWith("image/")) {
await this.addImageFile(file, nextSiblingElement);
}
}

document.querySelectorAll(".enable-on-file").forEach((element) => {
Expand Down Expand Up @@ -130,6 +136,25 @@ class PdfContainer {
}
}

async addImageFile(file, nextSiblingElement) {
const div = document.createElement("div");
div.classList.add("page-container");

var img = document.createElement("img");
img.classList.add("page-image");
img.src = URL.createObjectURL(file);

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.
div.appendChild(img);

this.pdfAdapters.forEach((adapter) => {
adapter.adapt?.(div);
});
if (nextSiblingElement) {
this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
this.pagesContainer.appendChild(div);
}
}

async loadFile(file) {
var objectUrl = URL.createObjectURL(file);
var pdfDocument = await this.toPdfLib(objectUrl);
Expand Down Expand Up @@ -193,16 +218,29 @@ class PdfContainer {
for (var i = 0; i < pageContainers.length; i++) {
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
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));
}
if (img.doc) {
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx]);
const page = pages[0];

pdfDoc.addPage(page);
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);
} else {
const page = pdfDoc.addPage([img.naturalWidth, img.naturalHeight]);
const imageBytes = await fetch(img.src).then((res) => res.arrayBuffer());
const image = await pdfDoc.embedPng(imageBytes);
page.drawImage(image, {
x: 0,
y: 0,
width: img.naturalWidth,
height: img.naturalHeight,
});
}
}
const pdfBytes = await pdfDoc.save();
const pdfBlob = new Blob([pdfBytes], { type: "application/pdf" });
Expand Down
19 changes: 19 additions & 0 deletions src/main/resources/static/js/multitool/fileInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,25 @@ class FileDragManager {
this.updateFilename(files ? files[0].name : "");
});
}

async addImageFile(file, nextSiblingElement) {
const div = document.createElement("div");
div.classList.add("page-container");

var img = document.createElement("img");
img.classList.add("page-image");
img.src = URL.createObjectURL(file);
div.appendChild(img);

this.pdfAdapters.forEach((adapter) => {
adapter.adapt?.(div);
});
if (nextSiblingElement) {
this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
this.pagesContainer.appendChild(div);
}
}
}

export default FileDragManager;
14 changes: 7 additions & 7 deletions src/main/resources/templates/multi-tool.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
th:placeholder="#{multiTool.uploadPrompts}">
</div>
<div class="mt-action-btn">
<button class="btn btn-primary" onclick="addPdfs()">
<button class="btn btn-primary" onclick="addFiles()">
<span class="material-symbols-rounded">
add
</span>
Expand All @@ -52,12 +52,12 @@
<div class="multi-tool-container">
<div class="d-flex flex-wrap" id="pages-container-wrapper">
<div id="pages-container">
<div class="page-container" th:each="pdf, status: ${pdfList}"
<div class="page-container" th:each="file, status: ${fileList}"
th:id="'page-container-' + ${status.index}">
<div class="page-number-container">
<span th:text="${status.index + 1}"></span>
</div>
<img th:src="${pdf.imageUrl}" alt="PDF Page">
<img th:src="${file.imageUrl}" alt="File Page">
</div>
</div>
</div>
Expand All @@ -82,14 +82,14 @@
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
// enables the default action buttons on each file
const pdfActionsManager = new PdfActionsManager('pages-container');
const fileDragManager = new FileDragManager();

// Scroll the wrapper horizontally
scrollDivHorizontally('pages-container-wrapper');

// Automatically exposes rotateAll, addPdfs and exportPdf to the window for the global buttons.
// Automatically exposes rotateAll, addFiles and exportPdf to the window for the global buttons.
const pdfContainer = new PdfContainer(
'pages-container',
'pages-container-wrapper',
Expand All @@ -101,8 +101,8 @@
]
)

fileDragManager.setCallback(async (files) => pdfContainer.addPdfsFromFiles(files));
fileDragManager.setCallback(async (files) => pdfContainer.addFilesFromFiles(files));
</script>
</body>

</html>
</html>

0 comments on commit 1006927

Please sign in to comment.