Dario Ghunney Ware 58c1bccfcc renamed module: enterprise > proprietary
updating paths (DOCKER_SECURITY_ENABLE > ADDITIONAL_FEATURES)
2025-06-05 18:13:50 +01:00

967 lines
32 KiB
JavaScript

import { MovePageCommand } from './commands/move-page.js';
import { RemoveSelectedCommand } from './commands/remove.js';
import { RotateAllCommand, RotateElementCommand } from './commands/rotate.js';
import { SplitAllCommand } from './commands/split.js';
import { UndoManager } from './UndoManager.js';
import { PageBreakCommand } from './commands/page-break.js';
import { AddFilesCommand } from './commands/add-page.js';
import { DecryptFile } from '../DecryptFiles.js';
import { CommandSequence } from './commands/commands-sequence.js';
class PdfContainer {
fileName;
pagesContainer;
pagesContainerWrapper;
pdfAdapters;
downloadLink;
undoManager;
constructor(id, wrapperId, pdfAdapters, undoManager) {
this.pagesContainer = document.getElementById(id);
this.pagesContainerWrapper = document.getElementById(wrapperId);
this.downloadLink = null;
this.movePageTo = this.movePageTo.bind(this);
this.addFiles = this.addFiles.bind(this);
this.addFilesFromFiles = this.addFilesFromFiles.bind(this);
this.rotateElement = this.rotateElement.bind(this);
this.rotateAll = this.rotateAll.bind(this);
this.exportPdf = this.exportPdf.bind(this);
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.nameAndArchiveFiles = this.nameAndArchiveFiles.bind(this);
this.splitPDF = this.splitPDF.bind(this);
this.splitAll = this.splitAll.bind(this);
this.deleteSelected = this.deleteSelected.bind(this);
this.selectAll = this.selectAll.bind(this);
this.deselectAll = this.deselectAll.bind(this);
this.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay.bind(this);
this.toggleSelectPageVisibility = this.toggleSelectPageVisibility.bind(this);
this.updatePagesFromCSV = this.updatePagesFromCSV.bind(this);
this.addFilesBlankAll = this.addFilesBlankAll.bind(this);
this.removeAllElements = this.removeAllElements.bind(this);
this.resetPages = this.resetPages.bind(this);
this.decryptFile = new DecryptFile();
this.undoManager = undoManager || new UndoManager();
this.pdfAdapters = pdfAdapters;
this.pdfAdapters.forEach((adapter) => {
adapter.setActions({
movePageTo: this.movePageTo,
addFiles: this.addFiles,
rotateElement: this.rotateElement,
updateFilename: this.updateFilename,
deleteSelected: this.deleteSelected,
});
});
window.addFiles = this.addFiles;
window.exportPdf = this.exportPdf;
window.rotateAll = this.rotateAll;
window.splitAll = this.splitAll;
window.deleteSelected = this.deleteSelected;
window.selectAll = this.selectAll;
window.deselectAll = this.deselectAll;
window.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay;
window.toggleSelectPageVisibility = this.toggleSelectPageVisibility;
window.updatePagesFromCSV = this.updatePagesFromCSV;
window.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay;
window.updatePageNumbersAndCheckboxes = this.updatePageNumbersAndCheckboxes;
window.addFilesBlankAll = this.addFilesBlankAll;
window.removeAllElements = this.removeAllElements;
window.resetPages = this.resetPages;
let undoBtn = document.getElementById('undo-btn');
let redoBtn = document.getElementById('redo-btn');
document.addEventListener('undo-manager-update', (e) => {
let canUndo = e.detail.canUndo;
let canRedo = e.detail.canRedo;
undoBtn.disabled = !canUndo;
redoBtn.disabled = !canRedo;
});
window.undo = () => {
if (undoManager.canUndo()) undoManager.undo();
else {
undoBtn.disabled = !undoManager.canUndo();
redoBtn.disabled = !undoManager.canRedo();
}
};
window.redo = () => {
if (undoManager.canRedo()) undoManager.redo();
else {
undoBtn.disabled = !undoManager.canUndo();
redoBtn.disabled = !undoManager.canRedo();
}
};
const filenameInput = document.getElementById('filename-input');
const downloadBtn = document.getElementById('export-button');
filenameInput.onkeyup = this.updateFilename;
filenameInput.onkeydown = this.preventIllegalChars;
filenameInput.disabled = false;
filenameInput.innerText = '';
downloadBtn.disabled = true;
}
movePagesTo(startElements, endElement, scrollTo = false) {
let commands = [];
startElements.forEach((page) => {
let command = new MovePageCommand(
page,
endElement,
this.pagesContainer,
this.pagesContainerWrapper,
scrollTo
)
command.execute();
commands.push(command);
})
let commandSequence = new CommandSequence(commands);
this.undoManager.pushUndoClearRedo(commandSequence);
return commandSequence;
}
showButton(button, show) {
button.classList.toggle('hidden', !show);
}
movePageTo(startElements, endElement, scrollTo = false) {
if (Array.isArray(startElements)){
return this.movePagesTo(startElements, endElement, scrollTo = false);
}
let movePageCommand = new MovePageCommand(
startElements,
endElement,
this.pagesContainer,
this.pagesContainerWrapper,
scrollTo
);
movePageCommand.execute();
this.undoManager.pushUndoClearRedo(movePageCommand);
return movePageCommand;
}
async addFiles(element) {
let addFilesCommand = new AddFilesCommand(
element,
window.selectedPages,
this.addFilesAction.bind(this),
this.pagesContainer
);
await addFilesCommand.execute();
this.undoManager.pushUndoClearRedo(addFilesCommand);
window.tooltipSetup();
}
async addFilesAction(nextSiblingElement) {
let pages = [];
return new Promise((resolve) => {
var input = document.createElement('input');
input.type = 'file';
input.multiple = true;
input.setAttribute('accept', 'application/pdf,image/*');
input.onchange = async (e) => {
const files = e.target.files;
if (files.length > 0) {
pages = await this.addFilesFromFiles(files, nextSiblingElement, pages);
this.updateFilename(files[0].name);
if(window.selectPage){
this.showButton(document.getElementById('select-pages-container'), true);
}
}
resolve(pages);
};
input.click();
});
}
async handleDroppedFiles(files, nextSiblingElement = null) {
if (files.length > 0) {
const pages = await this.addFilesFromFiles(files, nextSiblingElement, []);
this.updateFilename(files[0]?.name || 'untitled');
if(window.selectPage) {
this.showButton(document.getElementById('select-pages-container'), true);
}
return pages;
}
}
async addFilesFromFiles(files, nextSiblingElement, pages) {
this.fileName = files[0].name;
for (var i = 0; i < files.length; i++) {
const startTime = Date.now();
let processingTime,
errorMessage = null,
pageCount = 0;
try {
let decryptedFile = files[i];
let isEncrypted = false;
let requiresPassword = false;
await this.decryptFile
.checkFileEncrypted(decryptedFile)
.then((result) => {
isEncrypted = result.isEncrypted;
requiresPassword = result.requiresPassword;
})
.catch((error) => {
console.error(error);
});
if (decryptedFile.type === 'application/pdf' && isEncrypted) {
decryptedFile = await this.decryptFile.decryptFile(decryptedFile, requiresPassword);
if (!decryptedFile) {
throw new Error('File decryption failed.');
}
}
if (decryptedFile.type === 'application/pdf') {
const { renderer, pdfDocument } = await this.loadFile(decryptedFile);
pageCount = renderer.pageCount || 0;
pages = await this.addPdfFile(renderer, pdfDocument, nextSiblingElement, pages);
} else if (decryptedFile.type.startsWith('image/')) {
pages = await this.addImageFile(decryptedFile, nextSiblingElement, pages);
}
processingTime = Date.now() - startTime;
this.captureFileProcessingEvent(true, decryptedFile, processingTime, null, pageCount);
} catch (error) {
processingTime = Date.now() - startTime;
errorMessage = error.message || 'Unknown error';
this.captureFileProcessingEvent(false, files[i], processingTime, errorMessage, pageCount);
}
}
document.querySelectorAll('.enable-on-file').forEach((element) => {
element.disabled = false;
});
return pages;
}
captureFileProcessingEvent(success, file, processingTime, errorMessage, pageCount) {
try {
if (analyticsEnabled) {
posthog.capture('file_processing', {
success,
file_type: file?.type || 'unknown',
file_size: file?.size || 0,
processing_time: processingTime,
error_message: errorMessage,
pdf_pages: pageCount,
});
}
} catch { }
}
async addFilesBlank(nextSiblingElement, pages) {
let doc = await PDFLib.PDFDocument.create();
let docBytes = await doc.save();
const url = URL.createObjectURL(new Blob([docBytes], { type: 'application/pdf' }));
const renderer = await this.toRenderer(url);
pages = await this.addPdfFile(renderer, doc, nextSiblingElement, pages);
return pages;
}
rotateElement(element, deg) {
let rotateCommand = new RotateElementCommand(element, deg);
rotateCommand.execute();
return rotateCommand;
}
async addPdfFile(renderer, pdfDocument, nextSiblingElement, pages) {
for (var i = 0; i < renderer.pageCount; i++) {
const div = document.createElement('div');
div.classList.add('page-container');
div.id = 'page-container-' + (i + 1);
var img = document.createElement('img');
img.classList.add('page-image');
const imageSrc = await renderer.renderPage(i);
img.src = imageSrc;
img.pageIdx = i;
img.rend = renderer;
img.doc = pdfDocument;
div.appendChild(img);
this.pdfAdapters.forEach((adapter) => {
adapter.adapt?.(div);
});
if (nextSiblingElement) {
this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
this.pagesContainer.appendChild(div);
}
pages.push(div);
}
return pages;
}
async addImageFile(file, nextSiblingElement, pages) {
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);
}
pages.push(div);
return pages;
}
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) {
pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs';
const pdf = await pdfjsLib.getDocument(objectUrl).promise;
return {
document: pdf,
pageCount: pdf.numPages,
renderPage: async function (pageIdx) {
const page = await this.document.getPage(pageIdx + 1);
const canvas = document.createElement('canvas');
// set the canvas size to the size of the page
if (page.rotate == 90 || page.rotate == 270) {
canvas.width = page.view[3];
canvas.height = page.view[2];
} else {
canvas.width = page.view[2];
canvas.height = page.view[3];
}
// render the page onto the canvas
var renderContext = {
canvasContext: canvas.getContext('2d'),
viewport: page.getViewport({ scale: 1 }),
};
await page.render(renderContext).promise;
return canvas.toDataURL();
},
};
}
async toPdfLib(objectUrl) {
const existingPdfBytes = await fetch(objectUrl).then((res) => res.arrayBuffer());
const pdfDoc = await PDFLib.PDFDocument.load(existingPdfBytes, {
ignoreEncryption: true,
});
return pdfDoc;
}
rotateAll(deg) {
let elementsToRotate = [];
for (let i = 0; i < this.pagesContainer.childNodes.length; i++) {
const child = this.pagesContainer.children[i];
if (!child) continue;
const pageIndex = i + 1;
//if in page select mode is active rotate only selected pages
if (window.selectPage && !window.selectedPages.includes(pageIndex)) continue;
const img = child.querySelector('img');
if (!img) continue;
elementsToRotate.push(img);
}
let rotateAllCommand = new RotateAllCommand(elementsToRotate, deg);
rotateAllCommand.execute();
this.undoManager.pushUndoClearRedo(rotateAllCommand);
}
removeAllElements() {
let pageContainerNodeList = document.querySelectorAll('.page-container');
for (var i = 0; i < pageContainerNodeList.length; i++) {
pageContainerNodeList[i].remove();
}
document.querySelectorAll('.enable-on-file').forEach((element) => {
element.disabled = true;
});
}
deleteSelected() {
window.selectedPages.sort((a, b) => a - b);
let removeSelectedCommand = new RemoveSelectedCommand(
this.pagesContainer,
window.selectedPages,
this.updatePageNumbersAndCheckboxes
);
removeSelectedCommand.execute();
this.undoManager.pushUndoClearRedo(removeSelectedCommand);
}
selectAll() {
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
const selectIcon = document.getElementById('select-All-Container');
const deselectIcon = document.getElementById('deselect-All-Container');
this.showButton(selectIcon, false);
this.showButton(deselectIcon, true);
checkboxes.forEach((checkbox) => {
checkbox.checked = true;
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
if (!window.selectedPages.includes(pageNumber)) {
window.selectedPages.push(pageNumber);
}
});
this.updateSelectedPagesDisplay();
}
deselectAll() {
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
const selectIcon = document.getElementById('select-All-Container');
const deselectIcon = document.getElementById('deselect-All-Container');
this.showButton(selectIcon, true);
this.showButton(deselectIcon, false);
checkboxes.forEach((checkbox) => {
checkbox.checked = false;
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
const index = window.selectedPages.indexOf(pageNumber);
if (index !== -1) {
window.selectedPages.splice(index, 1);
}
});
this.updateSelectedPagesDisplay();
}
parseCSVInput(csvInput, maxPageIndex) {
const pages = new Set();
csvInput.split(',').forEach((item) => {
const range = item.split('-').map((p) => parseInt(p.trim()));
if (range.length === 2) {
const [start, end] = range;
for (let i = start; i <= end && i <= maxPageIndex; i++) {
if (i > 0) {
// Ensure the page number is greater than 0
pages.add(i);
}
}
} else if (range.length === 1 && Number.isInteger(range[0])) {
const page = range[0];
if (page > 0 && page <= maxPageIndex) {
// Ensure page is within valid range
pages.add(page);
}
}
});
return Array.from(pages).sort((a, b) => a - b);
}
updatePagesFromCSV() {
const csvInput = document.getElementById('csv-input').value;
const allPages = this.pagesContainer.querySelectorAll('.page-container');
const maxPageIndex = allPages.length;
window.selectedPages = this.parseCSVInput(csvInput, maxPageIndex);
this.updateSelectedPagesDisplay();
const allCheckboxes = document.querySelectorAll('.pdf-actions_checkbox');
allCheckboxes.forEach((checkbox) => {
const page = parseInt(checkbox.getAttribute('data-page-number'));
checkbox.checked = window.selectedPages.includes(page);
});
}
formatSelectedPages(pages) {
if (pages.length === 0) return '';
pages.sort((a, b) => a - b); // Sort the page numbers in ascending order
const ranges = [];
let start = pages[0];
let end = start;
for (let i = 1; i < pages.length; i++) {
if (pages[i] === end + 1) {
// Consecutive page, update end
end = pages[i];
} else {
// Non-consecutive page, finalize current range
ranges.push(start === end ? `${start}` : `${start}-${end}`);
start = pages[i];
end = start;
}
}
// Add the last range
ranges.push(start === end ? `${start}` : `${start}-${end}`);
return ranges.join(', ');
}
updateSelectedPagesDisplay() {
const selectedPagesList = document.getElementById('selected-pages-list');
const selectedPagesInput = document.getElementById('csv-input');
selectedPagesList.innerHTML = ''; // Clear the list
window.selectedPages.sort((a, b) => a - b);
window.selectedPages.forEach((page) => {
const pageItem = document.createElement('div');
pageItem.className = 'page-item';
const pageNumber = document.createElement('span');
const pagelabel = /*[[#{multiTool.page}]]*/ 'Page';
pageNumber.className = 'selected-page-number';
pageNumber.innerText = `${pagelabel} ${page}`;
pageItem.appendChild(pageNumber);
const removeBtn = document.createElement('span');
removeBtn.className = 'remove-btn';
removeBtn.innerHTML = '✕';
// Remove page from selected pages list and update display and checkbox
removeBtn.onclick = () => {
window.selectedPages = window.selectedPages.filter((p) => p !== page);
this.updateSelectedPagesDisplay();
const checkbox = document.getElementById(`selectPageCheckbox-${page}`);
if (checkbox) {
checkbox.checked = false;
}
};
pageItem.appendChild(removeBtn);
selectedPagesList.appendChild(pageItem);
});
// Update the input field with the formatted page list
selectedPagesInput.value = this.formatSelectedPages(window.selectedPages);
const selectIcon = document.getElementById('select-All-Container');
const deselectIcon = document.getElementById('deselect-All-Container');
if (window.selectPage) { // Check if selectPage mode is active
console.log("Page Select on. Showing buttons");
//Check if no pages are selected
if (window.selectedPages.length === 0) {
this.showButton(selectIcon, true);
this.showButton(deselectIcon, false);
} else {
this.showButton(deselectIcon, true);
}
//Check if all pages are selected
const allCheckboxes = document.querySelectorAll('.pdf-actions_checkbox');
const allSelected = Array.from(allCheckboxes).every((checkbox) => checkbox.checked);
if (allSelected) {
this.showButton(selectIcon, false);
this.showButton(deselectIcon, true);
} else {
this.showButton(selectIcon, true);
}
} else {
console.log("Page Select off. Hidding buttons");
this.showButton(selectIcon, false);
this.showButton(deselectIcon, false);
}
}
parsePageRanges(ranges) {
const pages = new Set();
ranges.split(',').forEach((range) => {
const [start, end] = range.split('-').map(Number);
if (end) {
for (let i = start; i <= end; i++) {
pages.add(i);
}
} else {
pages.add(start);
}
});
return Array.from(pages).sort((a, b) => a - b);
}
async addFilesBlankAll() {
const allPages = this.pagesContainer.querySelectorAll('.page-container');
let pageBreakCommand = new PageBreakCommand(
allPages,
window.selectPage,
window.selectedPages,
this.addFilesBlank.bind(this),
this.pagesContainer
);
await pageBreakCommand.execute();
this.undoManager.pushUndoClearRedo(pageBreakCommand);
}
splitAll() {
const allPages = this.pagesContainer.querySelectorAll('.page-container');
let splitAllCommand = new SplitAllCommand(allPages, window.selectPage, window.selectedPages, 'split-before');
splitAllCommand.execute();
this.undoManager.pushUndoClearRedo(splitAllCommand);
}
async splitPDF(baseDocBytes, splitters) {
const baseDocument = await PDFLib.PDFDocument.load(baseDocBytes);
const pageNum = baseDocument.getPages().length;
splitters.sort((a, b) => a - b); // We'll sort the separator indexes just in case querySelectorAll does something funny.
splitters.push(pageNum); // We'll also add a faux separator at the end in order to get the pages after the last separator.
const splitDocuments = [];
for (const splitterPosition of splitters) {
const subDocument = await PDFLib.PDFDocument.create();
const splitterIndex = splitters.indexOf(splitterPosition);
let firstPage = splitterIndex === 0 ? 0 : splitters[splitterIndex - 1];
const pageIndices = Array.from({ length: splitterPosition - firstPage }, (value, key) => firstPage + key);
const copiedPages = await subDocument.copyPages(baseDocument, pageIndices);
copiedPages.forEach((copiedPage) => {
subDocument.addPage(copiedPage);
});
const subDocumentBytes = await subDocument.save();
splitDocuments.push(subDocumentBytes);
}
return splitDocuments;
}
async nameAndArchiveFiles(pdfBytesArray, baseNameString) {
const zip = new JSZip();
for (let i = 0; i < pdfBytesArray.length; i++) {
const documentBlob = new Blob([pdfBytesArray[i]], {
type: 'application/pdf',
});
zip.file(baseNameString + '-' + (i + 1) + '.pdf', documentBlob);
}
return zip;
}
async exportPdf(selected) {
const pdfDoc = await PDFLib.PDFDocument.create();
const pageContainers = this.pagesContainer.querySelectorAll('.page-container'); // Select all .page-container elements
for (var i = 0; i < pageContainers.length; i++) {
if (!selected || window.selectedPages.includes(i + 1)) {
const img = pageContainers[i].querySelector('img'); // Find the img element within each .page-container
if (!img) continue;
let page;
if (img.doc) {
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx]);
page = pages[0];
pdfDoc.addPage(page);
} else {
page = pdfDoc.addPage([img.naturalWidth, img.naturalHeight]);
const imageBytes = await fetch(img.src).then((res) => res.arrayBuffer());
const uint8Array = new Uint8Array(imageBytes);
const imageType = detectImageType(uint8Array);
let image;
switch (imageType) {
case 'PNG':
image = await pdfDoc.embedPng(imageBytes);
break;
case 'JPEG':
image = await pdfDoc.embedJpg(imageBytes);
break;
case 'TIFF':
image = await pdfDoc.embedTiff(imageBytes);
break;
case 'GIF':
console.warn(`Unsupported image type: ${imageType}`);
continue; // Skip this image
default:
console.warn(`Unsupported image type: ${imageType}`);
continue; // Skip this image
}
page.drawImage(image, {
x: 0,
y: 0,
width: img.naturalWidth,
height: img.naturalHeight,
});
}
const rotation = img.style.rotate;
if (rotation) {
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle));
}
}
}
pdfDoc.setCreator(stirlingPDFLabel);
pdfDoc.setProducer(stirlingPDFLabel);
const pdfBytes = await pdfDoc.save();
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
const filenameInput = document.getElementById('filename-input');
let inputArr = filenameInput.value.split('.');
if (inputArr !== null && inputArr !== undefined && inputArr.length > 0) {
inputArr = inputArr.filter((n) => n); // remove all empty strings, nulls or undefined
if (inputArr.length > 1) {
inputArr.pop(); // remove right part after last dot
}
filenameInput.value = inputArr.join('');
this.fileName = filenameInput.value;
}
const separators = this.pagesContainer.querySelectorAll('.split-before');
if (separators.length !== 0) {
// Split the pdf if there are separators.
const baseName = this.fileName ? this.fileName : 'managed';
const pagesArray = Array.from(this.pagesContainer.children);
const splitters = [];
separators.forEach((page) => {
const pageIndex = pagesArray.indexOf(page);
if (pageIndex !== 0) {
splitters.push(pageIndex);
}
});
const splitDocuments = await this.splitPDF(pdfBytes, splitters);
const archivedDocuments = await this.nameAndArchiveFiles(splitDocuments, baseName);
const self = this;
archivedDocuments.generateAsync({ type: 'base64' }).then(function (base64) {
const url = 'data:application/zip;base64,' + base64;
self.downloadLink = document.createElement('a');
self.downloadLink.href = url;
self.downloadLink.setAttribute('download', baseName + '.zip');
self.downloadLink.setAttribute('target', '_blank');
self.downloadLink.click();
});
} else {
// Continue normally if there are no separators
const url = URL.createObjectURL(pdfBlob);
const downloadOption = localStorage.getItem('downloadOption');
if (!filenameInput.value.includes('.pdf')) {
filenameInput.value = filenameInput.value + '.pdf';
this.fileName = filenameInput.value;
}
if (downloadOption === 'sameWindow') {
// Open the file in the same window
window.location.href = url;
} else if (downloadOption === 'newWindow') {
// Open the file in a new window
window.open(url, '_blank');
} else {
// Download the file
this.downloadLink = document.createElement('a');
this.downloadLink.id = 'download-link';
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('target', '_blank');
this.downloadLink.onclick = this.setDownloadAttribute;
this.downloadLink.click();
}
}
}
resetPages() {
const pageContainers = this.pagesContainer.querySelectorAll('.page-container');
pageContainers.forEach((container, index) => {
container.id = 'page-container-' + (index + 1);
});
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
const selectIcon = document.getElementById('select-All-Container');
const deselectIcon = document.getElementById('deselect-All-Container');
checkboxes.forEach((checkbox) => {
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
const index = window.selectedPages.indexOf(pageNumber);
if (index !== -1) {
window.selectedPages.splice(index, 1);
}
});
window.toggleSelectPageVisibility();
}
setDownloadAttribute() {
this.downloadLink.setAttribute('download', this.fileName ? this.fileName : 'managed.pdf');
}
updateFilename(fileName = '') {
const filenameInput = document.getElementById('filename-input');
const pagesContainer = document.getElementById('pages-container');
const downloadBtn = document.getElementById('export-button');
downloadBtn.disabled = pagesContainer.childElementCount === 0;
if (!this.fileName) {
this.fileName = fileName;
}
if (!filenameInput.value) {
filenameInput.value = this.fileName;
}
}
preventIllegalChars(e) {
// const filenameInput = document.getElementById('filename-input');
//
// filenameInput.value = filenameInput.value.replace('.pdf', '');
//
// // prevent .
// if (filenameInput.value.includes('.')) {
// filenameInput.value.replace('.','');
// }
}
toggleSelectPageVisibility() {
window.selectPage = !window.selectPage;
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
checkboxes.forEach((checkbox) => {
checkbox.classList.toggle('hidden', !window.selectPage);
});
const deleteButton = document.getElementById('delete-button');
deleteButton.classList.toggle('hidden', !window.selectPage);
const selectedPages = document.getElementById('selected-pages-display');
selectedPages.classList.toggle('hidden', !window.selectPage);
if(!window.selectPage)
{
this.showButton(document.getElementById('deselect-All-Container'), false);
this.showButton(document.getElementById('select-All-Container'), false);
// Uncheck all checkboxes and clear selected pages
const allCheckboxes = document.querySelectorAll('.pdf-actions_checkbox');
allCheckboxes.forEach((checkbox) => {
checkbox.checked = false;
});
window.selectedPages = [];
this.updateSelectedPagesDisplay();
}
else{
const allCheckboxes = document.querySelectorAll('.pdf-actions_checkbox');
const allSelected = Array.from(allCheckboxes).every((checkbox) => checkbox.checked);
if (!allSelected) {
this.showButton(document.getElementById('select-All-Container'), true);
}
if (window.selectedPages.length > 0) {
this.showButton(document.getElementById('deselect-All-Container'), true);
}
}
const exportSelected = document.getElementById('export-selected-button');
exportSelected.classList.toggle('hidden', !window.selectPage);
const selectPagesButton = document.getElementById('select-pages-button');
selectPagesButton.style.opacity = window.selectPage ? '1' : '0.5';
if (window.selectPage) {
this.updatePageNumbersAndCheckboxes();
}
}
updatePageNumbersAndCheckboxes() {
const pageDivs = document.querySelectorAll('.pdf-actions_container');
pageDivs.forEach((div, index) => {
const pageNumber = index + 1;
const checkbox = div.querySelector('.pdf-actions_checkbox');
checkbox.id = `selectPageCheckbox-${pageNumber}`;
checkbox.setAttribute('data-page-number', pageNumber);
checkbox.checked = window.selectedPages.includes(pageNumber);
});
}
}
function detectImageType(uint8Array) {
// Check for PNG signature
if (uint8Array[0] === 137 && uint8Array[1] === 80 && uint8Array[2] === 78 && uint8Array[3] === 71) {
return 'PNG';
}
// Check for JPEG signature
if (uint8Array[0] === 255 && uint8Array[1] === 216 && uint8Array[2] === 255) {
return 'JPEG';
}
// Check for TIFF signature (little-endian and big-endian)
if (
(uint8Array[0] === 73 && uint8Array[1] === 73 && uint8Array[2] === 42 && uint8Array[3] === 0) ||
(uint8Array[0] === 77 && uint8Array[1] === 77 && uint8Array[2] === 0 && uint8Array[3] === 42)
) {
return 'TIFF';
}
// Check for GIF signature
if (uint8Array[0] === 71 && uint8Array[1] === 73 && uint8Array[2] === 70) {
return 'GIF';
}
return 'UNKNOWN';
}
export default PdfContainer;