mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-05-23 10:22:01 +00:00
Feature/undo page break (#2389)
* Fix delete selected Fix add page break where selected Added undo logic for page breaks * Add pages undo capability * Fix page break when selected logic
This commit is contained in:
parent
99d1b46d97
commit
d888ed1ae0
@ -1,8 +1,10 @@
|
|||||||
import { MovePageUpCommand, MovePageDownCommand } from "./commands/move-page.js";
|
import {MovePageUpCommand, MovePageDownCommand} from './commands/move-page.js';
|
||||||
import { RemoveSelectedCommand } from "./commands/remove.js";
|
import {RemoveSelectedCommand} from './commands/remove.js';
|
||||||
import { RotateAllCommand, RotateElementCommand } from "./commands/rotate.js";
|
import {RotateAllCommand, RotateElementCommand} from './commands/rotate.js';
|
||||||
import { SplitAllCommand } from "./commands/split.js";
|
import {SplitAllCommand} from './commands/split.js';
|
||||||
import { UndoManager } from "./UndoManager.js";
|
import {UndoManager} from './UndoManager.js';
|
||||||
|
import {PageBreakCommand} from './commands/page-break.js';
|
||||||
|
import {AddFilesCommand} from './commands/add-page.js';
|
||||||
|
|
||||||
class PdfContainer {
|
class PdfContainer {
|
||||||
fileName;
|
fileName;
|
||||||
@ -34,7 +36,7 @@ class PdfContainer {
|
|||||||
this.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay.bind(this);
|
this.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay.bind(this);
|
||||||
this.toggleSelectPageVisibility = this.toggleSelectPageVisibility.bind(this);
|
this.toggleSelectPageVisibility = this.toggleSelectPageVisibility.bind(this);
|
||||||
this.updatePagesFromCSV = this.updatePagesFromCSV.bind(this);
|
this.updatePagesFromCSV = this.updatePagesFromCSV.bind(this);
|
||||||
this.addFilesBlankAll = this.addFilesBlankAll.bind(this)
|
this.addFilesBlankAll = this.addFilesBlankAll.bind(this);
|
||||||
this.removeAllElements = this.removeAllElements.bind(this);
|
this.removeAllElements = this.removeAllElements.bind(this);
|
||||||
this.resetPages = this.resetPages.bind(this);
|
this.resetPages = this.resetPages.bind(this);
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ class PdfContainer {
|
|||||||
window.updatePagesFromCSV = this.updatePagesFromCSV;
|
window.updatePagesFromCSV = this.updatePagesFromCSV;
|
||||||
window.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay;
|
window.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay;
|
||||||
window.updatePageNumbersAndCheckboxes = this.updatePageNumbersAndCheckboxes;
|
window.updatePageNumbersAndCheckboxes = this.updatePageNumbersAndCheckboxes;
|
||||||
window.addFilesBlankAll = this.addFilesBlankAll
|
window.addFilesBlankAll = this.addFilesBlankAll;
|
||||||
window.removeAllElements = this.removeAllElements;
|
window.removeAllElements = this.removeAllElements;
|
||||||
window.resetPages = this.resetPages;
|
window.resetPages = this.resetPages;
|
||||||
|
|
||||||
@ -76,7 +78,7 @@ class PdfContainer {
|
|||||||
|
|
||||||
undoBtn.disabled = !canUndo;
|
undoBtn.disabled = !canUndo;
|
||||||
redoBtn.disabled = !canRedo;
|
redoBtn.disabled = !canRedo;
|
||||||
})
|
});
|
||||||
|
|
||||||
window.undo = () => {
|
window.undo = () => {
|
||||||
if (undoManager.canUndo()) undoManager.undo();
|
if (undoManager.canUndo()) undoManager.undo();
|
||||||
@ -84,7 +86,7 @@ class PdfContainer {
|
|||||||
undoBtn.disabled = !undoManager.canUndo();
|
undoBtn.disabled = !undoManager.canUndo();
|
||||||
redoBtn.disabled = !undoManager.canRedo();
|
redoBtn.disabled = !undoManager.canRedo();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
window.redo = () => {
|
window.redo = () => {
|
||||||
if (undoManager.canRedo()) undoManager.redo();
|
if (undoManager.canRedo()) undoManager.redo();
|
||||||
@ -92,15 +94,15 @@ class PdfContainer {
|
|||||||
undoBtn.disabled = !undoManager.canUndo();
|
undoBtn.disabled = !undoManager.canUndo();
|
||||||
redoBtn.disabled = !undoManager.canRedo();
|
redoBtn.disabled = !undoManager.canRedo();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const filenameInput = document.getElementById("filename-input");
|
const filenameInput = document.getElementById('filename-input');
|
||||||
const downloadBtn = document.getElementById("export-button");
|
const downloadBtn = document.getElementById('export-button');
|
||||||
|
|
||||||
filenameInput.onkeyup = this.updateFilename;
|
filenameInput.onkeyup = this.updateFilename;
|
||||||
filenameInput.onkeydown = this.preventIllegalChars;
|
filenameInput.onkeydown = this.preventIllegalChars;
|
||||||
filenameInput.disabled = false;
|
filenameInput.disabled = false;
|
||||||
filenameInput.innerText = "";
|
filenameInput.innerText = '';
|
||||||
downloadBtn.disabled = true;
|
downloadBtn.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,60 +130,76 @@ class PdfContainer {
|
|||||||
return movePageCommand;
|
return movePageCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
addFiles(nextSiblingElement, blank = false) {
|
async addFiles(element) {
|
||||||
if (blank) {
|
let addFilesCommand = new AddFilesCommand(
|
||||||
|
element,
|
||||||
|
window.selectedPages,
|
||||||
|
this.addFilesAction.bind(this),
|
||||||
|
this.pagesContainer
|
||||||
|
);
|
||||||
|
|
||||||
this.addFilesBlank(nextSiblingElement);
|
await addFilesCommand.execute();
|
||||||
|
|
||||||
} else {
|
this.undoManager.pushUndoClearRedo(addFilesCommand);
|
||||||
var input = document.createElement("input");
|
}
|
||||||
input.type = "file";
|
|
||||||
|
async addFilesAction(nextSiblingElement) {
|
||||||
|
let pages = [];
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
var input = document.createElement('input');
|
||||||
|
input.type = 'file';
|
||||||
input.multiple = true;
|
input.multiple = true;
|
||||||
input.setAttribute("accept", "application/pdf,image/*");
|
input.setAttribute('accept', 'application/pdf,image/*');
|
||||||
|
|
||||||
input.onchange = async (e) => {
|
input.onchange = async (e) => {
|
||||||
const files = e.target.files;
|
const files = e.target.files;
|
||||||
|
if (files.length > 0) {
|
||||||
this.addFilesFromFiles(files, nextSiblingElement);
|
pages = await this.addFilesFromFiles(files, nextSiblingElement, pages);
|
||||||
this.updateFilename(files ? files[0].name : "");
|
this.updateFilename(files[0].name);
|
||||||
const selectAll = document.getElementById("select-pages-container");
|
const selectAll = document.getElementById('select-pages-container');
|
||||||
selectAll.classList.toggle("hidden", false);
|
selectAll.classList.toggle('hidden', false);
|
||||||
|
}
|
||||||
|
resolve(pages);
|
||||||
};
|
};
|
||||||
|
|
||||||
input.click();
|
input.click();
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async addFilesFromFiles(files, nextSiblingElement) {
|
async addFilesFromFiles(files, nextSiblingElement, pages) {
|
||||||
this.fileName = files[0].name;
|
this.fileName = files[0].name;
|
||||||
for (var i = 0; i < files.length; i++) {
|
for (var i = 0; i < files.length; i++) {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
let processingTime, errorMessage = null, pageCount = 0;
|
let processingTime,
|
||||||
|
errorMessage = null,
|
||||||
|
pageCount = 0;
|
||||||
try {
|
try {
|
||||||
const file = files[i];
|
const file = files[i];
|
||||||
if (file.type === "application/pdf") {
|
if (file.type === 'application/pdf') {
|
||||||
const { renderer, pdfDocument } = await this.loadFile(file);
|
const {renderer, pdfDocument} = await this.loadFile(file);
|
||||||
pageCount = renderer.pageCount || 0;
|
pageCount = renderer.pageCount || 0;
|
||||||
await this.addPdfFile(renderer, pdfDocument, nextSiblingElement);
|
pages = await this.addPdfFile(renderer, pdfDocument, nextSiblingElement, pages);
|
||||||
} else if (file.type.startsWith("image/")) {
|
} else if (file.type.startsWith('image/')) {
|
||||||
await this.addImageFile(file, nextSiblingElement);
|
pages = await this.addImageFile(file, nextSiblingElement, pages);
|
||||||
}
|
}
|
||||||
processingTime = Date.now() - startTime;
|
processingTime = Date.now() - startTime;
|
||||||
this.captureFileProcessingEvent(true, file, processingTime, null, pageCount);
|
this.captureFileProcessingEvent(true, file, processingTime, null, pageCount);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
processingTime = Date.now() - startTime;
|
processingTime = Date.now() - startTime;
|
||||||
errorMessage = error.message || "Unknown error";
|
errorMessage = error.message || 'Unknown error';
|
||||||
this.captureFileProcessingEvent(false, files[i], processingTime, errorMessage, pageCount);
|
this.captureFileProcessingEvent(false, files[i], processingTime, errorMessage, pageCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelectorAll(".enable-on-file").forEach((element) => {
|
document.querySelectorAll('.enable-on-file').forEach((element) => {
|
||||||
element.disabled = false;
|
element.disabled = false;
|
||||||
});
|
});
|
||||||
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
captureFileProcessingEvent(success, file, processingTime, errorMessage, pageCount) {
|
captureFileProcessingEvent(success, file, processingTime, errorMessage, pageCount) {
|
||||||
try{
|
try {
|
||||||
if(analyticsEnabled){
|
if (analyticsEnabled) {
|
||||||
posthog.capture('file_processing', {
|
posthog.capture('file_processing', {
|
||||||
success,
|
success,
|
||||||
file_type: file?.type || 'unknown',
|
file_type: file?.type || 'unknown',
|
||||||
@ -190,24 +208,21 @@ class PdfContainer {
|
|||||||
error_message: errorMessage,
|
error_message: errorMessage,
|
||||||
pdf_pages: pageCount,
|
pdf_pages: pageCount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}catch{
|
} catch {}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
async addFilesBlank(nextSiblingElement, pages) {
|
||||||
async addFilesBlank(nextSiblingElement) {
|
|
||||||
let doc = await PDFLib.PDFDocument.create();
|
let doc = await PDFLib.PDFDocument.create();
|
||||||
let docBytes = await doc.save();
|
let docBytes = await doc.save();
|
||||||
|
|
||||||
const url = URL.createObjectURL(new Blob([docBytes], { type: 'application/pdf' }));
|
const url = URL.createObjectURL(new Blob([docBytes], {type: 'application/pdf'}));
|
||||||
|
|
||||||
const renderer = await this.toRenderer(url);
|
const renderer = await this.toRenderer(url);
|
||||||
|
pages = await this.addPdfFile(renderer, doc, nextSiblingElement, pages);
|
||||||
await this.addPdfFile(renderer, doc, nextSiblingElement);
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rotateElement(element, deg) {
|
rotateElement(element, deg) {
|
||||||
let rotateCommand = new RotateElementCommand(element, deg);
|
let rotateCommand = new RotateElementCommand(element, deg);
|
||||||
rotateCommand.execute();
|
rotateCommand.execute();
|
||||||
@ -215,37 +230,43 @@ class PdfContainer {
|
|||||||
return rotateCommand;
|
return rotateCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addPdfFile(renderer, pdfDocument, nextSiblingElement) {
|
async addPdfFile(renderer, pdfDocument, nextSiblingElement, pages) {
|
||||||
for (var i = 0; i < renderer.pageCount; i++) {
|
for (var i = 0; i < renderer.pageCount; i++) {
|
||||||
const div = document.createElement("div");
|
const div = document.createElement('div');
|
||||||
|
|
||||||
div.classList.add("page-container");
|
div.classList.add('page-container');
|
||||||
div.id = "page-container-" + (i + 1);
|
div.id = 'page-container-' + (i + 1);
|
||||||
var img = document.createElement("img");
|
var img = document.createElement('img');
|
||||||
img.classList.add("page-image");
|
img.classList.add('page-image');
|
||||||
const imageSrc = await renderer.renderPage(i);
|
const imageSrc = await renderer.renderPage(i);
|
||||||
img.src = imageSrc;
|
img.src = imageSrc;
|
||||||
img.pageIdx = i;
|
img.pageIdx = i;
|
||||||
img.rend = renderer;
|
img.rend = renderer;
|
||||||
img.doc = pdfDocument;
|
img.doc = pdfDocument;
|
||||||
div.appendChild(img);
|
div.appendChild(img);
|
||||||
|
|
||||||
this.pdfAdapters.forEach((adapter) => {
|
this.pdfAdapters.forEach((adapter) => {
|
||||||
adapter.adapt?.(div);
|
adapter.adapt?.(div);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (nextSiblingElement) {
|
if (nextSiblingElement) {
|
||||||
this.pagesContainer.insertBefore(div, nextSiblingElement);
|
this.pagesContainer.insertBefore(div, nextSiblingElement);
|
||||||
} else {
|
} else {
|
||||||
this.pagesContainer.appendChild(div);
|
this.pagesContainer.appendChild(div);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
pages.push(div);
|
||||||
}
|
}
|
||||||
|
|
||||||
async addImageFile(file, nextSiblingElement) {
|
return pages;
|
||||||
const div = document.createElement("div");
|
}
|
||||||
div.classList.add("page-container");
|
|
||||||
|
|
||||||
var img = document.createElement("img");
|
async addImageFile(file, nextSiblingElement, pages) {
|
||||||
img.classList.add("page-image");
|
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);
|
img.src = URL.createObjectURL(file);
|
||||||
div.appendChild(img);
|
div.appendChild(img);
|
||||||
|
|
||||||
@ -257,17 +278,19 @@ class PdfContainer {
|
|||||||
} else {
|
} else {
|
||||||
this.pagesContainer.appendChild(div);
|
this.pagesContainer.appendChild(div);
|
||||||
}
|
}
|
||||||
|
pages.push(div);
|
||||||
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadFile(file) {
|
async loadFile(file) {
|
||||||
var objectUrl = URL.createObjectURL(file);
|
var objectUrl = URL.createObjectURL(file);
|
||||||
var pdfDocument = await this.toPdfLib(objectUrl);
|
var pdfDocument = await this.toPdfLib(objectUrl);
|
||||||
var renderer = await this.toRenderer(objectUrl);
|
var renderer = await this.toRenderer(objectUrl);
|
||||||
return { renderer, pdfDocument };
|
return {renderer, pdfDocument};
|
||||||
}
|
}
|
||||||
|
|
||||||
async toRenderer(objectUrl) {
|
async toRenderer(objectUrl) {
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc = "./pdfjs-legacy/pdf.worker.mjs";
|
pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs';
|
||||||
const pdf = await pdfjsLib.getDocument(objectUrl).promise;
|
const pdf = await pdfjsLib.getDocument(objectUrl).promise;
|
||||||
return {
|
return {
|
||||||
document: pdf,
|
document: pdf,
|
||||||
@ -275,7 +298,7 @@ class PdfContainer {
|
|||||||
renderPage: async function (pageIdx) {
|
renderPage: async function (pageIdx) {
|
||||||
const page = await this.document.getPage(pageIdx + 1);
|
const page = await this.document.getPage(pageIdx + 1);
|
||||||
|
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement('canvas');
|
||||||
|
|
||||||
// set the canvas size to the size of the page
|
// set the canvas size to the size of the page
|
||||||
if (page.rotate == 90 || page.rotate == 270) {
|
if (page.rotate == 90 || page.rotate == 270) {
|
||||||
@ -288,8 +311,8 @@ class PdfContainer {
|
|||||||
|
|
||||||
// render the page onto the canvas
|
// render the page onto the canvas
|
||||||
var renderContext = {
|
var renderContext = {
|
||||||
canvasContext: canvas.getContext("2d"),
|
canvasContext: canvas.getContext('2d'),
|
||||||
viewport: page.getViewport({ scale: 1 }),
|
viewport: page.getViewport({scale: 1}),
|
||||||
};
|
};
|
||||||
|
|
||||||
await page.render(renderContext).promise;
|
await page.render(renderContext).promise;
|
||||||
@ -316,7 +339,7 @@ class PdfContainer {
|
|||||||
//if in page select mode is active rotate only selected pages
|
//if in page select mode is active rotate only selected pages
|
||||||
if (window.selectPage && !window.selectedPages.includes(pageIndex)) continue;
|
if (window.selectPage && !window.selectedPages.includes(pageIndex)) continue;
|
||||||
|
|
||||||
const img = child.querySelector("img");
|
const img = child.querySelector('img');
|
||||||
if (!img) continue;
|
if (!img) continue;
|
||||||
|
|
||||||
elementsToRotate.push(img);
|
elementsToRotate.push(img);
|
||||||
@ -328,12 +351,12 @@ class PdfContainer {
|
|||||||
this.undoManager.pushUndoClearRedo(rotateAllCommand);
|
this.undoManager.pushUndoClearRedo(rotateAllCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllElements(){
|
removeAllElements() {
|
||||||
let pageContainerNodeList = document.querySelectorAll(".page-container");
|
let pageContainerNodeList = document.querySelectorAll('.page-container');
|
||||||
for (var i = 0; i < pageContainerNodeList.length; i++) {
|
for (var i = 0; i < pageContainerNodeList.length; i++) {
|
||||||
pageContainerNodeList[i].remove();
|
pageContainerNodeList[i].remove();
|
||||||
}
|
}
|
||||||
document.querySelectorAll(".enable-on-file").forEach((element) => {
|
document.querySelectorAll('.enable-on-file').forEach((element) => {
|
||||||
element.disabled = true;
|
element.disabled = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -345,25 +368,24 @@ class PdfContainer {
|
|||||||
window.selectedPages,
|
window.selectedPages,
|
||||||
this.updatePageNumbersAndCheckboxes
|
this.updatePageNumbersAndCheckboxes
|
||||||
);
|
);
|
||||||
|
removeSelectedCommand.execute();
|
||||||
this.undoManager.pushUndoClearRedo(removeSelectedCommand);
|
this.undoManager.pushUndoClearRedo(removeSelectedCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSelectAll() {
|
toggleSelectAll() {
|
||||||
const checkboxes = document.querySelectorAll(".pdf-actions_checkbox");
|
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
|
||||||
window.selectAll = !window.selectAll;
|
window.selectAll = !window.selectAll;
|
||||||
const selectIcon = document.getElementById("select-All-Container");
|
const selectIcon = document.getElementById('select-All-Container');
|
||||||
const deselectIcon = document.getElementById("deselect-All-Container");
|
const deselectIcon = document.getElementById('deselect-All-Container');
|
||||||
|
|
||||||
if (selectIcon.style.display === "none") {
|
if (selectIcon.style.display === 'none') {
|
||||||
selectIcon.style.display = "inline";
|
selectIcon.style.display = 'inline';
|
||||||
deselectIcon.style.display = "none";
|
deselectIcon.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
selectIcon.style.display = "none";
|
selectIcon.style.display = 'none';
|
||||||
deselectIcon.style.display = "inline";
|
deselectIcon.style.display = 'inline';
|
||||||
}
|
}
|
||||||
checkboxes.forEach((checkbox) => {
|
checkboxes.forEach((checkbox) => {
|
||||||
|
|
||||||
checkbox.checked = window.selectAll;
|
checkbox.checked = window.selectAll;
|
||||||
|
|
||||||
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
|
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
|
||||||
@ -386,18 +408,20 @@ class PdfContainer {
|
|||||||
parseCSVInput(csvInput, maxPageIndex) {
|
parseCSVInput(csvInput, maxPageIndex) {
|
||||||
const pages = new Set();
|
const pages = new Set();
|
||||||
|
|
||||||
csvInput.split(",").forEach((item) => {
|
csvInput.split(',').forEach((item) => {
|
||||||
const range = item.split("-").map((p) => parseInt(p.trim()));
|
const range = item.split('-').map((p) => parseInt(p.trim()));
|
||||||
if (range.length === 2) {
|
if (range.length === 2) {
|
||||||
const [start, end] = range;
|
const [start, end] = range;
|
||||||
for (let i = start; i <= end && i <= maxPageIndex; i++) {
|
for (let i = start; i <= end && i <= maxPageIndex; i++) {
|
||||||
if (i > 0) { // Ensure the page number is greater than 0
|
if (i > 0) {
|
||||||
|
// Ensure the page number is greater than 0
|
||||||
pages.add(i);
|
pages.add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (range.length === 1 && Number.isInteger(range[0])) {
|
} else if (range.length === 1 && Number.isInteger(range[0])) {
|
||||||
const page = range[0];
|
const page = range[0];
|
||||||
if (page > 0 && page <= maxPageIndex) { // Ensure page is within valid range
|
if (page > 0 && page <= maxPageIndex) {
|
||||||
|
// Ensure page is within valid range
|
||||||
pages.add(page);
|
pages.add(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,24 +431,24 @@ class PdfContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updatePagesFromCSV() {
|
updatePagesFromCSV() {
|
||||||
const csvInput = document.getElementById("csv-input").value;
|
const csvInput = document.getElementById('csv-input').value;
|
||||||
|
|
||||||
const allPages = this.pagesContainer.querySelectorAll(".page-container");
|
const allPages = this.pagesContainer.querySelectorAll('.page-container');
|
||||||
const maxPageIndex = allPages.length;
|
const maxPageIndex = allPages.length;
|
||||||
|
|
||||||
window.selectedPages = this.parseCSVInput(csvInput, maxPageIndex);
|
window.selectedPages = this.parseCSVInput(csvInput, maxPageIndex);
|
||||||
|
|
||||||
this.updateSelectedPagesDisplay();
|
this.updateSelectedPagesDisplay();
|
||||||
|
|
||||||
const allCheckboxes = document.querySelectorAll(".pdf-actions_checkbox");
|
const allCheckboxes = document.querySelectorAll('.pdf-actions_checkbox');
|
||||||
allCheckboxes.forEach((checkbox) => {
|
allCheckboxes.forEach((checkbox) => {
|
||||||
const page = parseInt(checkbox.getAttribute("data-page-number"));
|
const page = parseInt(checkbox.getAttribute('data-page-number'));
|
||||||
checkbox.checked = window.selectedPages.includes(page);
|
checkbox.checked = window.selectedPages.includes(page);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
formatSelectedPages(pages) {
|
formatSelectedPages(pages) {
|
||||||
if (pages.length === 0) return "";
|
if (pages.length === 0) return '';
|
||||||
|
|
||||||
pages.sort((a, b) => a - b); // Sort the page numbers in ascending order
|
pages.sort((a, b) => a - b); // Sort the page numbers in ascending order
|
||||||
const ranges = [];
|
const ranges = [];
|
||||||
@ -445,27 +469,27 @@ class PdfContainer {
|
|||||||
// Add the last range
|
// Add the last range
|
||||||
ranges.push(start === end ? `${start}` : `${start}-${end}`);
|
ranges.push(start === end ? `${start}` : `${start}-${end}`);
|
||||||
|
|
||||||
return ranges.join(", ");
|
return ranges.join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSelectedPagesDisplay() {
|
updateSelectedPagesDisplay() {
|
||||||
const selectedPagesList = document.getElementById("selected-pages-list");
|
const selectedPagesList = document.getElementById('selected-pages-list');
|
||||||
const selectedPagesInput = document.getElementById("csv-input");
|
const selectedPagesInput = document.getElementById('csv-input');
|
||||||
selectedPagesList.innerHTML = ""; // Clear the list
|
selectedPagesList.innerHTML = ''; // Clear the list
|
||||||
window.selectedPages.sort((a, b) => a - b);
|
window.selectedPages.sort((a, b) => a - b);
|
||||||
window.selectedPages.forEach((page) => {
|
window.selectedPages.forEach((page) => {
|
||||||
const pageItem = document.createElement("div");
|
const pageItem = document.createElement('div');
|
||||||
pageItem.className = "page-item";
|
pageItem.className = 'page-item';
|
||||||
|
|
||||||
const pageNumber = document.createElement("span");
|
const pageNumber = document.createElement('span');
|
||||||
const pagelabel = /*[[#{multiTool.page}]]*/ 'Page';
|
const pagelabel = /*[[#{multiTool.page}]]*/ 'Page';
|
||||||
pageNumber.className = "selected-page-number";
|
pageNumber.className = 'selected-page-number';
|
||||||
pageNumber.innerText = `${pagelabel} ${page}`;
|
pageNumber.innerText = `${pagelabel} ${page}`;
|
||||||
pageItem.appendChild(pageNumber);
|
pageItem.appendChild(pageNumber);
|
||||||
|
|
||||||
const removeBtn = document.createElement("span");
|
const removeBtn = document.createElement('span');
|
||||||
removeBtn.className = "remove-btn";
|
removeBtn.className = 'remove-btn';
|
||||||
removeBtn.innerHTML = "✕";
|
removeBtn.innerHTML = '✕';
|
||||||
|
|
||||||
// Remove page from selected pages list and update display and checkbox
|
// Remove page from selected pages list and update display and checkbox
|
||||||
removeBtn.onclick = () => {
|
removeBtn.onclick = () => {
|
||||||
@ -489,7 +513,7 @@ class PdfContainer {
|
|||||||
parsePageRanges(ranges) {
|
parsePageRanges(ranges) {
|
||||||
const pages = new Set();
|
const pages = new Set();
|
||||||
|
|
||||||
ranges.split(',').forEach(range => {
|
ranges.split(',').forEach((range) => {
|
||||||
const [start, end] = range.split('-').map(Number);
|
const [start, end] = range.split('-').map(Number);
|
||||||
if (end) {
|
if (end) {
|
||||||
for (let i = start; i <= end; i++) {
|
for (let i = start; i <= end; i++) {
|
||||||
@ -503,23 +527,25 @@ class PdfContainer {
|
|||||||
return Array.from(pages).sort((a, b) => a - b);
|
return Array.from(pages).sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
addFilesBlankAll() {
|
async addFilesBlankAll() {
|
||||||
const allPages = this.pagesContainer.querySelectorAll(".page-container");
|
const allPages = this.pagesContainer.querySelectorAll('.page-container');
|
||||||
allPages.forEach((page, index) => {
|
|
||||||
if (index !== 0) {
|
|
||||||
this.addFiles(page, true)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
splitAll() {
|
let pageBreakCommand = new PageBreakCommand(
|
||||||
const allPages = this.pagesContainer.querySelectorAll(".page-container");
|
|
||||||
let splitAllCommand = new SplitAllCommand(
|
|
||||||
allPages,
|
allPages,
|
||||||
window.selectPage,
|
window.selectPage,
|
||||||
window.selectedPages,
|
window.selectedPages,
|
||||||
"split-before"
|
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();
|
splitAllCommand.execute();
|
||||||
|
|
||||||
this.undoManager.pushUndoClearRedo(splitAllCommand);
|
this.undoManager.pushUndoClearRedo(splitAllCommand);
|
||||||
@ -529,7 +555,7 @@ class PdfContainer {
|
|||||||
const baseDocument = await PDFLib.PDFDocument.load(baseDocBytes);
|
const baseDocument = await PDFLib.PDFDocument.load(baseDocBytes);
|
||||||
const pageNum = baseDocument.getPages().length;
|
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.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.
|
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 = [];
|
const splitDocuments = [];
|
||||||
@ -540,18 +566,18 @@ class PdfContainer {
|
|||||||
|
|
||||||
let firstPage = splitterIndex === 0 ? 0 : splitters[splitterIndex - 1];
|
let firstPage = splitterIndex === 0 ? 0 : splitters[splitterIndex - 1];
|
||||||
|
|
||||||
const pageIndices = Array.from({ length: splitterPosition - firstPage }, (value, key) => firstPage + key);
|
const pageIndices = Array.from({length: splitterPosition - firstPage}, (value, key) => firstPage + key);
|
||||||
|
|
||||||
const copiedPages = await subDocument.copyPages(baseDocument, pageIndices);
|
const copiedPages = await subDocument.copyPages(baseDocument, pageIndices);
|
||||||
|
|
||||||
copiedPages.forEach(copiedPage => {
|
copiedPages.forEach((copiedPage) => {
|
||||||
subDocument.addPage(copiedPage);
|
subDocument.addPage(copiedPage);
|
||||||
});
|
});
|
||||||
|
|
||||||
const subDocumentBytes = await subDocument.save();
|
const subDocumentBytes = await subDocument.save();
|
||||||
|
|
||||||
splitDocuments.push(subDocumentBytes);
|
splitDocuments.push(subDocumentBytes);
|
||||||
};
|
}
|
||||||
|
|
||||||
return splitDocuments;
|
return splitDocuments;
|
||||||
}
|
}
|
||||||
@ -560,8 +586,10 @@ class PdfContainer {
|
|||||||
const zip = new JSZip();
|
const zip = new JSZip();
|
||||||
|
|
||||||
for (let i = 0; i < pdfBytesArray.length; i++) {
|
for (let i = 0; i < pdfBytesArray.length; i++) {
|
||||||
const documentBlob = new Blob([pdfBytesArray[i]], { type: "application/pdf" });
|
const documentBlob = new Blob([pdfBytesArray[i]], {
|
||||||
zip.file(baseNameString + "-" + (i + 1) + ".pdf", documentBlob);
|
type: 'application/pdf',
|
||||||
|
});
|
||||||
|
zip.file(baseNameString + '-' + (i + 1) + '.pdf', documentBlob);
|
||||||
}
|
}
|
||||||
|
|
||||||
return zip;
|
return zip;
|
||||||
@ -569,10 +597,10 @@ class PdfContainer {
|
|||||||
|
|
||||||
async exportPdf(selected) {
|
async exportPdf(selected) {
|
||||||
const pdfDoc = await PDFLib.PDFDocument.create();
|
const pdfDoc = await PDFLib.PDFDocument.create();
|
||||||
const pageContainers = this.pagesContainer.querySelectorAll(".page-container"); // Select all .page-container elements
|
const pageContainers = this.pagesContainer.querySelectorAll('.page-container'); // Select all .page-container elements
|
||||||
for (var i = 0; i < pageContainers.length; i++) {
|
for (var i = 0; i < pageContainers.length; i++) {
|
||||||
if (!selected || window.selectedPages.includes(i + 1)) {
|
if (!selected || window.selectedPages.includes(i + 1)) {
|
||||||
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
|
const img = pageContainers[i].querySelector('img'); // Find the img element within each .page-container
|
||||||
if (!img) continue;
|
if (!img) continue;
|
||||||
let page;
|
let page;
|
||||||
if (img.doc) {
|
if (img.doc) {
|
||||||
@ -612,7 +640,7 @@ class PdfContainer {
|
|||||||
}
|
}
|
||||||
const rotation = img.style.rotate;
|
const rotation = img.style.rotate;
|
||||||
if (rotation) {
|
if (rotation) {
|
||||||
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ""));
|
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
|
||||||
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle));
|
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,11 +649,11 @@ class PdfContainer {
|
|||||||
pdfDoc.setProducer(stirlingPDFLabel);
|
pdfDoc.setProducer(stirlingPDFLabel);
|
||||||
|
|
||||||
const pdfBytes = await pdfDoc.save();
|
const pdfBytes = await pdfDoc.save();
|
||||||
const pdfBlob = new Blob([pdfBytes], { type: "application/pdf" });
|
const pdfBlob = new Blob([pdfBytes], {type: 'application/pdf'});
|
||||||
|
|
||||||
const filenameInput = document.getElementById("filename-input");
|
const filenameInput = document.getElementById('filename-input');
|
||||||
|
|
||||||
let inputArr = filenameInput.value.split(".");
|
let inputArr = filenameInput.value.split('.');
|
||||||
|
|
||||||
if (inputArr !== null && inputArr !== undefined && inputArr.length > 0) {
|
if (inputArr !== null && inputArr !== undefined && inputArr.length > 0) {
|
||||||
inputArr = inputArr.filter((n) => n); // remove all empty strings, nulls or undefined
|
inputArr = inputArr.filter((n) => n); // remove all empty strings, nulls or undefined
|
||||||
@ -634,17 +662,18 @@ class PdfContainer {
|
|||||||
inputArr.pop(); // remove right part after last dot
|
inputArr.pop(); // remove right part after last dot
|
||||||
}
|
}
|
||||||
|
|
||||||
filenameInput.value = inputArr.join("");
|
filenameInput.value = inputArr.join('');
|
||||||
this.fileName = filenameInput.value;
|
this.fileName = filenameInput.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const separators = this.pagesContainer.querySelectorAll(".split-before");
|
const separators = this.pagesContainer.querySelectorAll('.split-before');
|
||||||
if (separators.length !== 0) { // Split the pdf if there are separators.
|
if (separators.length !== 0) {
|
||||||
const baseName = this.fileName ? this.fileName : "managed";
|
// Split the pdf if there are separators.
|
||||||
|
const baseName = this.fileName ? this.fileName : 'managed';
|
||||||
|
|
||||||
const pagesArray = Array.from(this.pagesContainer.children);
|
const pagesArray = Array.from(this.pagesContainer.children);
|
||||||
const splitters = [];
|
const splitters = [];
|
||||||
separators.forEach(page => {
|
separators.forEach((page) => {
|
||||||
const pageIndex = pagesArray.indexOf(page);
|
const pageIndex = pagesArray.indexOf(page);
|
||||||
if (pageIndex !== 0) {
|
if (pageIndex !== 0) {
|
||||||
splitters.push(pageIndex);
|
splitters.push(pageIndex);
|
||||||
@ -655,40 +684,40 @@ class PdfContainer {
|
|||||||
const archivedDocuments = await this.nameAndArchiveFiles(splitDocuments, baseName);
|
const archivedDocuments = await this.nameAndArchiveFiles(splitDocuments, baseName);
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
archivedDocuments.generateAsync({ type: "base64" }).then(function (base64) {
|
archivedDocuments.generateAsync({type: 'base64'}).then(function (base64) {
|
||||||
const url = "data:application/zip;base64," + base64;
|
const url = 'data:application/zip;base64,' + base64;
|
||||||
self.downloadLink = document.createElement("a");
|
self.downloadLink = document.createElement('a');
|
||||||
self.downloadLink.href = url;
|
self.downloadLink.href = url;
|
||||||
self.downloadLink.setAttribute("download", baseName + ".zip");
|
self.downloadLink.setAttribute('download', baseName + '.zip');
|
||||||
self.downloadLink.setAttribute("target", "_blank");
|
self.downloadLink.setAttribute('target', '_blank');
|
||||||
self.downloadLink.click();
|
self.downloadLink.click();
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
} else { // Continue normally if there are no separators
|
// Continue normally if there are no separators
|
||||||
|
|
||||||
const url = URL.createObjectURL(pdfBlob);
|
const url = URL.createObjectURL(pdfBlob);
|
||||||
const downloadOption = localStorage.getItem("downloadOption");
|
const downloadOption = localStorage.getItem('downloadOption');
|
||||||
|
|
||||||
if (!filenameInput.value.includes(".pdf")) {
|
if (!filenameInput.value.includes('.pdf')) {
|
||||||
filenameInput.value = filenameInput.value + ".pdf";
|
filenameInput.value = filenameInput.value + '.pdf';
|
||||||
this.fileName = filenameInput.value;
|
this.fileName = filenameInput.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadOption === "sameWindow") {
|
if (downloadOption === 'sameWindow') {
|
||||||
// Open the file in the same window
|
// Open the file in the same window
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
} else if (downloadOption === "newWindow") {
|
} else if (downloadOption === 'newWindow') {
|
||||||
// Open the file in a new window
|
// Open the file in a new window
|
||||||
window.open(url, "_blank");
|
window.open(url, '_blank');
|
||||||
} else {
|
} else {
|
||||||
// Download the file
|
// Download the file
|
||||||
this.downloadLink = document.createElement("a");
|
this.downloadLink = document.createElement('a');
|
||||||
this.downloadLink.id = "download-link";
|
this.downloadLink.id = 'download-link';
|
||||||
this.downloadLink.href = url;
|
this.downloadLink.href = url;
|
||||||
// downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
|
// downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
|
||||||
// downloadLink.download = this.fileName;
|
// 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.setAttribute('target', '_blank');
|
||||||
this.downloadLink.onclick = this.setDownloadAttribute;
|
this.downloadLink.onclick = this.setDownloadAttribute;
|
||||||
this.downloadLink.click();
|
this.downloadLink.click();
|
||||||
}
|
}
|
||||||
@ -696,19 +725,19 @@ class PdfContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resetPages() {
|
resetPages() {
|
||||||
const pageContainers = this.pagesContainer.querySelectorAll(".page-container");
|
const pageContainers = this.pagesContainer.querySelectorAll('.page-container');
|
||||||
|
|
||||||
pageContainers.forEach((container, index) => {
|
pageContainers.forEach((container, index) => {
|
||||||
container.id = "page-container-" + (index + 1);
|
container.id = 'page-container-' + (index + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
const checkboxes = document.querySelectorAll(".pdf-actions_checkbox");
|
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
|
||||||
window.selectAll = false;
|
window.selectAll = false;
|
||||||
const selectIcon = document.getElementById("select-All-Container");
|
const selectIcon = document.getElementById('select-All-Container');
|
||||||
const deselectIcon = document.getElementById("deselect-All-Container");
|
const deselectIcon = document.getElementById('deselect-All-Container');
|
||||||
|
|
||||||
selectIcon.style.display = "inline";
|
selectIcon.style.display = 'inline';
|
||||||
deselectIcon.style.display = "none";
|
deselectIcon.style.display = 'none';
|
||||||
|
|
||||||
checkboxes.forEach((checkbox) => {
|
checkboxes.forEach((checkbox) => {
|
||||||
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
|
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
|
||||||
@ -722,13 +751,13 @@ class PdfContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setDownloadAttribute() {
|
setDownloadAttribute() {
|
||||||
this.downloadLink.setAttribute("download", this.fileName ? this.fileName : "managed.pdf");
|
this.downloadLink.setAttribute('download', this.fileName ? this.fileName : 'managed.pdf');
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFilename(fileName = "") {
|
updateFilename(fileName = '') {
|
||||||
const filenameInput = document.getElementById("filename-input");
|
const filenameInput = document.getElementById('filename-input');
|
||||||
const pagesContainer = document.getElementById("pages-container");
|
const pagesContainer = document.getElementById('pages-container');
|
||||||
const downloadBtn = document.getElementById("export-button");
|
const downloadBtn = document.getElementById('export-button');
|
||||||
|
|
||||||
downloadBtn.disabled = pagesContainer.childElementCount === 0;
|
downloadBtn.disabled = pagesContainer.childElementCount === 0;
|
||||||
|
|
||||||
@ -752,38 +781,36 @@ class PdfContainer {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
toggleSelectPageVisibility() {
|
toggleSelectPageVisibility() {
|
||||||
window.selectPage = !window.selectPage;
|
window.selectPage = !window.selectPage;
|
||||||
const checkboxes = document.querySelectorAll(".pdf-actions_checkbox");
|
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
|
||||||
checkboxes.forEach(checkbox => {
|
checkboxes.forEach((checkbox) => {
|
||||||
checkbox.classList.toggle("hidden", !window.selectPage);
|
checkbox.classList.toggle('hidden', !window.selectPage);
|
||||||
});
|
});
|
||||||
const deleteButton = document.getElementById("delete-button");
|
const deleteButton = document.getElementById('delete-button');
|
||||||
deleteButton.classList.toggle("hidden", !window.selectPage);
|
deleteButton.classList.toggle('hidden', !window.selectPage);
|
||||||
const selectedPages = document.getElementById("selected-pages-display");
|
const selectedPages = document.getElementById('selected-pages-display');
|
||||||
selectedPages.classList.toggle("hidden", !window.selectPage);
|
selectedPages.classList.toggle('hidden', !window.selectPage);
|
||||||
const selectAll = document.getElementById("select-All-Container");
|
const selectAll = document.getElementById('select-All-Container');
|
||||||
selectAll.classList.toggle("hidden", !window.selectPage);
|
selectAll.classList.toggle('hidden', !window.selectPage);
|
||||||
const exportSelected = document.getElementById("export-selected-button");
|
const exportSelected = document.getElementById('export-selected-button');
|
||||||
exportSelected.classList.toggle("hidden", !window.selectPage);
|
exportSelected.classList.toggle('hidden', !window.selectPage);
|
||||||
const selectPagesButton = document.getElementById("select-pages-button");
|
const selectPagesButton = document.getElementById('select-pages-button');
|
||||||
selectPagesButton.style.opacity = window.selectPage ? "1" : "0.5";
|
selectPagesButton.style.opacity = window.selectPage ? '1' : '0.5';
|
||||||
|
|
||||||
if (window.selectPage) {
|
if (window.selectPage) {
|
||||||
this.updatePageNumbersAndCheckboxes();
|
this.updatePageNumbersAndCheckboxes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
updatePageNumbersAndCheckboxes() {
|
updatePageNumbersAndCheckboxes() {
|
||||||
const pageDivs = document.querySelectorAll(".pdf-actions_container");
|
const pageDivs = document.querySelectorAll('.pdf-actions_container');
|
||||||
|
|
||||||
pageDivs.forEach((div, index) => {
|
pageDivs.forEach((div, index) => {
|
||||||
const pageNumber = index + 1;
|
const pageNumber = index + 1;
|
||||||
const checkbox = div.querySelector(".pdf-actions_checkbox");
|
const checkbox = div.querySelector('.pdf-actions_checkbox');
|
||||||
checkbox.id = `selectPageCheckbox-${pageNumber}`;
|
checkbox.id = `selectPageCheckbox-${pageNumber}`;
|
||||||
checkbox.setAttribute("data-page-number", pageNumber);
|
checkbox.setAttribute('data-page-number', pageNumber);
|
||||||
checkbox.checked = window.selectedPages.includes(pageNumber);
|
checkbox.checked = window.selectedPages.includes(pageNumber);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -801,8 +828,10 @@ function detectImageType(uint8Array) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for TIFF signature (little-endian and big-endian)
|
// Check for TIFF signature (little-endian and big-endian)
|
||||||
if ((uint8Array[0] === 73 && uint8Array[1] === 73 && uint8Array[2] === 42 && uint8Array[3] === 0) ||
|
if (
|
||||||
(uint8Array[0] === 77 && uint8Array[1] === 77 && uint8Array[2] === 0 && uint8Array[3] === 42)) {
|
(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';
|
return 'TIFF';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,6 +843,4 @@ function detectImageType(uint8Array) {
|
|||||||
return 'UNKNOWN';
|
return 'UNKNOWN';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default PdfContainer;
|
export default PdfContainer;
|
||||||
|
53
src/main/resources/static/js/multitool/commands/add-page.js
Normal file
53
src/main/resources/static/js/multitool/commands/add-page.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import {Command} from './command.js';
|
||||||
|
|
||||||
|
export class AddFilesCommand extends Command {
|
||||||
|
constructor(element, selectedPages, addFilesAction, pagesContainer) {
|
||||||
|
super();
|
||||||
|
this.element = element;
|
||||||
|
this.selectedPages = selectedPages;
|
||||||
|
this.addFilesAction = addFilesAction;
|
||||||
|
this.pagesContainer = pagesContainer;
|
||||||
|
this.addedElements = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute() {
|
||||||
|
const undoBtn = document.getElementById('undo-btn');
|
||||||
|
undoBtn.disabled = true;
|
||||||
|
if (this.element) {
|
||||||
|
const newElement = await this.addFilesAction(this.element);
|
||||||
|
if (newElement) {
|
||||||
|
this.addedElements = newElement;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const newElement = await this.addFilesAction(false);
|
||||||
|
if (newElement) {
|
||||||
|
this.addedElements = newElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
undoBtn.disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
undo() {
|
||||||
|
this.addedElements.forEach((element) => {
|
||||||
|
const nextSibling = element.nextSibling;
|
||||||
|
this.pagesContainer.removeChild(element);
|
||||||
|
|
||||||
|
if (this.pagesContainer.childElementCount === 0) {
|
||||||
|
const filenameInput = document.getElementById('filename-input');
|
||||||
|
const filenameParagraph = document.getElementById('filename');
|
||||||
|
const downloadBtn = document.getElementById('export-button');
|
||||||
|
|
||||||
|
filenameInput.disabled = true;
|
||||||
|
filenameInput.value = '';
|
||||||
|
filenameParagraph.innerText = '';
|
||||||
|
downloadBtn.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
element._nextSibling = nextSibling;
|
||||||
|
});
|
||||||
|
this.addedElements = [];
|
||||||
|
}
|
||||||
|
redo() {
|
||||||
|
this.execute();
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,9 @@ export class DeletePageCommand extends Command {
|
|||||||
this.filenameInputValue = document.getElementById("filename-input").value;
|
this.filenameInputValue = document.getElementById("filename-input").value;
|
||||||
|
|
||||||
const filenameParagraph = document.getElementById("filename");
|
const filenameParagraph = document.getElementById("filename");
|
||||||
this.filenameParagraphText = filenameParagraph ? filenameParagraph.innerText : "";
|
this.filenameParagraphText = filenameParagraph
|
||||||
|
? filenameParagraph.innerText
|
||||||
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
execute() {
|
execute() {
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
import {Command} from './command.js';
|
||||||
|
|
||||||
|
export class PageBreakCommand extends Command {
|
||||||
|
constructor(elements, isSelectedInWindow, selectedPages, pageBreakCallback, pagesContainer) {
|
||||||
|
super();
|
||||||
|
this.elements = elements;
|
||||||
|
this.isSelectedInWindow = isSelectedInWindow;
|
||||||
|
this.selectedPages = selectedPages;
|
||||||
|
this.pageBreakCallback = pageBreakCallback;
|
||||||
|
this.pagesContainer = pagesContainer;
|
||||||
|
this.addedElements = [];
|
||||||
|
this.originalStates = Array.from(elements, (element) => ({
|
||||||
|
element,
|
||||||
|
hasContent: element.innerHTML.trim() !== '',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute() {
|
||||||
|
const undoBtn = document.getElementById('undo-btn');
|
||||||
|
undoBtn.disabled = true;
|
||||||
|
for (const [index, element] of this.elements.entries()) {
|
||||||
|
if (!this.isSelectedInWindow || this.selectedPages.includes(index)) {
|
||||||
|
if (index !== 0) {
|
||||||
|
const newElement = await this.pageBreakCallback(element, this.addedElements);
|
||||||
|
|
||||||
|
if (newElement) {
|
||||||
|
this.addedElements = newElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
undoBtn.disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
undo() {
|
||||||
|
this.addedElements.forEach((element) => {
|
||||||
|
const nextSibling = element.nextSibling;
|
||||||
|
|
||||||
|
this.pagesContainer.removeChild(element);
|
||||||
|
|
||||||
|
if (this.pagesContainer.childElementCount === 0) {
|
||||||
|
const filenameInput = document.getElementById('filename-input');
|
||||||
|
const filenameParagraph = document.getElementById('filename');
|
||||||
|
const downloadBtn = document.getElementById('export-button');
|
||||||
|
|
||||||
|
filenameInput.disabled = true;
|
||||||
|
filenameInput.value = '';
|
||||||
|
filenameParagraph.innerText = '';
|
||||||
|
downloadBtn.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
element._nextSibling = nextSibling;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
redo() {
|
||||||
|
this.execute();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user