* Implement Command class for Command Pattern Created a base `Command` class to implement the **Command Pattern**. This class provides a skeletal implementation for `execute`, `undo`, and `redo` methods. **Note:** This class is intended to be subclassed and not instantiated directly. * Add undo/redo stacks and operations * Use rotate element command to perform execute/undo/redo operations * Handle commands executed through events - Add "command-execution" event listener to execute commands that are not invoked from the same class while adding the command to the undo stack and clearing the redo stack. * Add and use rotate all command to rotate/redo/undo all elements * Use command pattern to delete pages * Use command pattern for page selection * Use command pattern to move pages up and down * Use command pattern to remove selected pages * Use command pattern to perform the splitting operation * Add undo/redo functionality with filename input exclusion - Implement undo (Ctrl+Z) and redo (Ctrl+Y) functionality. - Prevent undo/redo actions when the filename input field is focused. - Ensures proper handling of undo/redo actions without interfering with text editing. * Introduce UndoManager for managing undo/redo operations - Encapsulate undo/redo stacks and operations within UndoManager. - Simplify handling of undo/redo functionality through a dedicated manager. * Call execute on splitAllCommand - Fix a bug that caused split all functionality to not work as execute() wasn't called on splitAllCommand * Add undo/redo buttons to multi tool - Add undo/redo buttons to multi tool - Dispatch an event upon state change (such as changes in the undo/redo stacks) to update the UI accordingly. * Add undo/redo to translations * Replace hard-coded "Undo"/"Redo" with translation keys in multi tool --------- Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
102 lines
3.3 KiB
JavaScript
102 lines
3.3 KiB
JavaScript
import { Command } from "./command.js";
|
|
|
|
export class RemoveSelectedCommand extends Command {
|
|
constructor(pagesContainer, selectedPages, updatePageNumbersAndCheckboxes) {
|
|
super();
|
|
this.pagesContainer = pagesContainer;
|
|
this.selectedPages = selectedPages;
|
|
|
|
this.deletedChildren = [];
|
|
|
|
if (updatePageNumbersAndCheckboxes) {
|
|
this.updatePageNumbersAndCheckboxes = updatePageNumbersAndCheckboxes;
|
|
} else {
|
|
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);
|
|
});
|
|
}
|
|
|
|
const filenameInput = document.getElementById("filename-input");
|
|
const filenameParagraph = document.getElementById("filename");
|
|
|
|
this.originalFilenameInputValue = filenameInput ? filenameInput.value : "";
|
|
if (filenameParagraph)
|
|
this.originalFilenameParagraphText = filenameParagraph.innerText;
|
|
}
|
|
|
|
execute() {
|
|
let deletions = 0;
|
|
|
|
this.selectedPages.forEach((pageIndex) => {
|
|
const adjustedIndex = pageIndex - 1 - deletions;
|
|
const child = this.pagesContainer.children[adjustedIndex];
|
|
if (child) {
|
|
this.pagesContainer.removeChild(child);
|
|
deletions++;
|
|
|
|
this.deletedChildren.push({
|
|
idx: adjustedIndex,
|
|
childNode: child,
|
|
});
|
|
}
|
|
});
|
|
|
|
if (this.pagesContainer.childElementCount === 0) {
|
|
const filenameInput = document.getElementById("filename-input");
|
|
const filenameParagraph = document.getElementById("filename");
|
|
const downloadBtn = document.getElementById("export-button");
|
|
|
|
if (filenameInput) filenameInput.disabled = true;
|
|
filenameInput.value = "";
|
|
if (filenameParagraph) filenameParagraph.innerText = "";
|
|
|
|
downloadBtn.disabled = true;
|
|
}
|
|
|
|
window.selectedPages = [];
|
|
this.updatePageNumbersAndCheckboxes();
|
|
document.dispatchEvent(new Event("selectedPagesUpdated"));
|
|
}
|
|
|
|
undo() {
|
|
while (this.deletedChildren.length > 0) {
|
|
let deletedChild = this.deletedChildren.pop();
|
|
if (this.pagesContainer.children.length <= deletedChild.idx)
|
|
this.pagesContainer.appendChild(deletedChild.childNode);
|
|
else {
|
|
this.pagesContainer.insertBefore(
|
|
deletedChild.childNode,
|
|
this.pagesContainer.children[deletedChild.idx]
|
|
);
|
|
}
|
|
}
|
|
|
|
if (this.pagesContainer.childElementCount > 0) {
|
|
const filenameInput = document.getElementById("filename-input");
|
|
const filenameParagraph = document.getElementById("filename");
|
|
const downloadBtn = document.getElementById("export-button");
|
|
|
|
if (filenameInput) filenameInput.disabled = false;
|
|
filenameInput.value = this.originalFilenameInputValue;
|
|
if (filenameParagraph)
|
|
filenameParagraph.innerText = this.originalFilenameParagraphText;
|
|
|
|
downloadBtn.disabled = false;
|
|
}
|
|
|
|
window.selectedPages = this.selectedPages;
|
|
this.updatePageNumbersAndCheckboxes();
|
|
document.dispatchEvent(new Event("selectedPagesUpdated"));
|
|
}
|
|
|
|
redo() {
|
|
this.execute();
|
|
}
|
|
}
|