Merge branch 'main' into patch-1
This commit is contained in:
commit
a4544d7943
7 changed files with 177 additions and 87 deletions
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
@ -1,6 +1,6 @@
|
||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
github: Frooodle # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
open_collective: # Replace with a single Open Collective username
|
open_collective: # Replace with a single Open Collective username
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
[![Docker Image Version (tag latest semver)](https://img.shields.io/docker/v/frooodle/s-pdf/latest)](https://github.com/Frooodle/Stirling-PDF/)
|
[![Docker Image Version (tag latest semver)](https://img.shields.io/docker/v/frooodle/s-pdf/latest)](https://github.com/Frooodle/Stirling-PDF/)
|
||||||
[![GitHub Repo stars](https://img.shields.io/github/stars/frooodle/stirling-pdf?style=social)](https://github.com/Frooodle/stirling-pdf)
|
[![GitHub Repo stars](https://img.shields.io/github/stars/frooodle/stirling-pdf?style=social)](https://github.com/Frooodle/stirling-pdf)
|
||||||
[![Paypal Donate](https://img.shields.io/badge/Paypal%20Donate-yellow?style=flat&logo=paypal)](https://www.paypal.com/paypalme/froodleplex)
|
[![Paypal Donate](https://img.shields.io/badge/Paypal%20Donate-yellow?style=flat&logo=paypal)](https://www.paypal.com/paypalme/froodleplex)
|
||||||
|
[![Github Sponser](https://img.shields.io/badge/Github%20Sponsor-yellow?style=flat&logo=github)](https://github.com/sponsors/Frooodle)
|
||||||
|
|
||||||
This is a powerful locally hosted web based PDF manipulation tool using docker that allows you to perform various operations on PDF files, such as splitting merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application started as a 100% ChatGPT-made application and has evolved to include a wide range of features to handle all your PDF needs.
|
This is a powerful locally hosted web based PDF manipulation tool using docker that allows you to perform various operations on PDF files, such as splitting merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application started as a 100% ChatGPT-made application and has evolved to include a wide range of features to handle all your PDF needs.
|
||||||
|
|
||||||
|
@ -42,6 +43,8 @@ Feel free to request any features of bug fixes either in github issues or our [D
|
||||||
- [OcrMyPdf](https://github.com/ocrmypdf/OCRmyPDF)
|
- [OcrMyPdf](https://github.com/ocrmypdf/OCRmyPDF)
|
||||||
- HTML, CSS, JavaScript
|
- HTML, CSS, JavaScript
|
||||||
- Docker
|
- Docker
|
||||||
|
- PDF.js
|
||||||
|
- PDF-LIB.js
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ dependencies {
|
||||||
implementation 'commons-io:commons-io:2.11.0'
|
implementation 'commons-io:commons-io:2.11.0'
|
||||||
|
|
||||||
//general PDF
|
//general PDF
|
||||||
implementation 'org.apache.pdfbox:pdfbox:2.0.27'
|
implementation 'org.apache.pdfbox:pdfbox:2.0.28'
|
||||||
|
|
||||||
implementation 'com.itextpdf:itextpdf:5.5.13.3'
|
implementation 'com.itextpdf:itextpdf:5.5.13.3'
|
||||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||||
|
|
|
@ -21,3 +21,17 @@ html[lang-direction=rtl] * {
|
||||||
direction: rtl;
|
direction: rtl;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.align-top {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.align-center-right {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
.align-bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<script src="pdfjs/pdf.js"></script>
|
<script src="pdfjs/pdf.js"></script>
|
||||||
|
|
||||||
<!-- PDF-Lib -->
|
<!-- PDF-Lib -->
|
||||||
<script src="pdf-lib.min.js"></script>
|
<script src="js/pdf-lib.min.js"></script>
|
||||||
|
|
||||||
<!-- Custom -->
|
<!-- Custom -->
|
||||||
<link rel="stylesheet" href="css/general.css">
|
<link rel="stylesheet" href="css/general.css">
|
||||||
|
|
|
@ -23,21 +23,21 @@
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-secondary" onclick="rotateAll(-90)">
|
<button class="btn btn-secondary enable-on-file" onclick="rotateAll(-90)" disabled>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
|
||||||
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z" />
|
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z" />
|
||||||
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
|
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-secondary" onclick="rotateAll(90)">
|
<button class="btn btn-secondary enable-on-file" onclick="rotateAll(90)" disabled>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
|
||||||
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
|
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
|
||||||
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
|
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button id="export-button" class="btn btn-primary" onclick="exportPdf()">
|
<button id="export-button" class="btn btn-primary enable-on-file" onclick="exportPdf()" disabled>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download" viewBox="0 0 16 16">
|
||||||
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
|
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
|
||||||
<path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
|
<path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
|
||||||
|
@ -56,45 +56,50 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var myDocument = null;
|
var fileName = null;
|
||||||
var myRenderer = null;
|
|
||||||
const pagesContainer = document.getElementById("pages-container");
|
const pagesContainer = document.getElementById("pages-container");
|
||||||
|
|
||||||
function addPdfs() {
|
// add the bottom "insert pdf" button that appears on the right when hovered over
|
||||||
|
const bottomInsertFileButtonContainer = document.createElement('div');
|
||||||
|
bottomInsertFileButtonContainer.classList.add("insert-file-button-container", "align-bottom");
|
||||||
|
bottomInsertFileButtonContainer.style.transform = "translate(0, 50%)";
|
||||||
|
|
||||||
|
const bottomInsertFileButton = document.createElement('button');
|
||||||
|
bottomInsertFileButton.classList.add("btn", "btn-primary", "insert-file-button", "align-center-right");
|
||||||
|
bottomInsertFileButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
|
||||||
|
<path d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z"/>
|
||||||
|
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
|
||||||
|
</svg>`;
|
||||||
|
bottomInsertFileButton.onclick = e => addPdfs();
|
||||||
|
bottomInsertFileButtonContainer.appendChild(bottomInsertFileButton);
|
||||||
|
|
||||||
|
pagesContainer.appendChild(bottomInsertFileButtonContainer);
|
||||||
|
|
||||||
|
function addPdfs(nextSiblingElement) {
|
||||||
var input = document.createElement('input');
|
var input = document.createElement('input');
|
||||||
input.type = 'file';
|
input.type = 'file';
|
||||||
input.multiple = true;
|
input.multiple = true;
|
||||||
|
input.setAttribute("accept", "application/pdf");
|
||||||
|
|
||||||
input.onchange = async(e) => {
|
input.onchange = async(e) => {
|
||||||
const files = e.target.files;
|
const files = e.target.files;
|
||||||
|
fileName = files[0].name;
|
||||||
for (var i=0; i < files.length; i++) {
|
for (var i=0; i < files.length; i++) {
|
||||||
addPdfFile(files[i]);
|
addPdfFile(files[i], nextSiblingElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll(".enable-on-file").forEach(element => {
|
||||||
|
element.disabled = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
input.click();
|
input.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addPdfFile(file) {
|
async function addPdfFile(file, nextSiblingElement) {
|
||||||
const { renderer, pdfDocument } = await loadFile(file);
|
const { renderer, pdfDocument } = await loadFile(file);
|
||||||
for (var i=0; i < renderer.pageCount; i++) {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
div.classList.add("page-container");
|
|
||||||
|
|
||||||
var img = document.createElement('img');
|
const moveUpButtonCallback = e => {
|
||||||
img.src = await renderer.renderPage(i);
|
|
||||||
img.pageIdx = i;
|
|
||||||
img.rend = renderer;
|
|
||||||
img.doc = pdfDocument;
|
|
||||||
div.appendChild(img);
|
|
||||||
|
|
||||||
const buttonContainer = document.createElement('div');
|
|
||||||
buttonContainer.classList.add("button-container");
|
|
||||||
|
|
||||||
const moveUp = document.createElement('button');
|
|
||||||
moveUp.classList.add("move-up-button","btn", "btn-secondary");
|
|
||||||
moveUp.innerHTML = '<i class="bi bi-arrow-up-short"></i>';
|
|
||||||
moveUp.onclick = e => {
|
|
||||||
var imgContainer = e.target;
|
var imgContainer = e.target;
|
||||||
while (!imgContainer.classList.contains("page-container")) {
|
while (!imgContainer.classList.contains("page-container")) {
|
||||||
imgContainer = imgContainer.parentNode;
|
imgContainer = imgContainer.parentNode;
|
||||||
|
@ -110,13 +115,8 @@
|
||||||
block: "center",
|
block: "center",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
buttonContainer.appendChild(moveUp);
|
const moveDownButtonCallback = e => {
|
||||||
|
|
||||||
const moveDown = document.createElement('button');
|
|
||||||
moveDown.classList.add("move-down-button","btn", "btn-secondary");
|
|
||||||
moveDown.innerHTML = '<i class="bi bi-arrow-down-short"></i>';
|
|
||||||
moveDown.onclick = e => {
|
|
||||||
var imgContainer = e.target;
|
var imgContainer = e.target;
|
||||||
while (!imgContainer.classList.contains("page-container")) {
|
while (!imgContainer.classList.contains("page-container")) {
|
||||||
imgContainer = imgContainer.parentNode;
|
imgContainer = imgContainer.parentNode;
|
||||||
|
@ -138,7 +138,64 @@
|
||||||
block: "center",
|
block: "center",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
const rotateCCWButtonCallback = e => {
|
||||||
|
var imgContainer = e.target;
|
||||||
|
while (!imgContainer.classList.contains("page-container")) {
|
||||||
|
imgContainer = imgContainer.parentNode;
|
||||||
}
|
}
|
||||||
|
const img = imgContainer.querySelector("img");
|
||||||
|
|
||||||
|
rotateElement(img, -90)
|
||||||
|
};
|
||||||
|
const rotateCWButtonCallback = e => {
|
||||||
|
var imgContainer = e.target;
|
||||||
|
while (!imgContainer.classList.contains("page-container")) {
|
||||||
|
imgContainer = imgContainer.parentNode;
|
||||||
|
}
|
||||||
|
const img = imgContainer.querySelector("img");
|
||||||
|
|
||||||
|
rotateElement(img, 90)
|
||||||
|
};
|
||||||
|
const deletePageButtonCallback = e => {
|
||||||
|
var imgContainer = e.target;
|
||||||
|
while (!imgContainer.classList.contains("page-container")) {
|
||||||
|
imgContainer = imgContainer.parentNode;
|
||||||
|
}
|
||||||
|
pagesContainer.removeChild(imgContainer);
|
||||||
|
};
|
||||||
|
const insertFileButtonCallback = e => {
|
||||||
|
var imgContainer = e.target;
|
||||||
|
while (!imgContainer.classList.contains("page-container")) {
|
||||||
|
imgContainer = imgContainer.parentNode;
|
||||||
|
}
|
||||||
|
addPdfs(imgContainer)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i=0; i < renderer.pageCount; i++) {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.classList.add("page-container");
|
||||||
|
|
||||||
|
var img = document.createElement('img');
|
||||||
|
img.src = await renderer.renderPage(i);
|
||||||
|
img.pageIdx = i;
|
||||||
|
img.rend = renderer;
|
||||||
|
img.doc = pdfDocument;
|
||||||
|
div.appendChild(img);
|
||||||
|
|
||||||
|
const buttonContainer = document.createElement('div');
|
||||||
|
buttonContainer.classList.add("button-container");
|
||||||
|
|
||||||
|
const moveUp = document.createElement('button');
|
||||||
|
moveUp.classList.add("move-up-button","btn", "btn-secondary");
|
||||||
|
moveUp.innerHTML = '<i class="bi bi-arrow-up-short"></i>';
|
||||||
|
moveUp.onclick = moveUpButtonCallback;
|
||||||
|
buttonContainer.appendChild(moveUp);
|
||||||
|
|
||||||
|
const moveDown = document.createElement('button');
|
||||||
|
moveDown.classList.add("move-down-button","btn", "btn-secondary");
|
||||||
|
moveDown.innerHTML = '<i class="bi bi-arrow-down-short"></i>';
|
||||||
|
moveDown.onclick = moveDownButtonCallback;
|
||||||
buttonContainer.appendChild(moveDown);
|
buttonContainer.appendChild(moveDown);
|
||||||
|
|
||||||
const rotateCCW = document.createElement('button');
|
const rotateCCW = document.createElement('button');
|
||||||
|
@ -147,15 +204,7 @@
|
||||||
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z" />
|
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z" />
|
||||||
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
|
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
|
||||||
</svg>`;
|
</svg>`;
|
||||||
rotateCCW.onclick = e => {
|
rotateCCW.onclick = rotateCCWButtonCallback;
|
||||||
var imgContainer = e.target;
|
|
||||||
while (!imgContainer.classList.contains("page-container")) {
|
|
||||||
imgContainer = imgContainer.parentNode;
|
|
||||||
}
|
|
||||||
const img = imgContainer.querySelector("img");
|
|
||||||
|
|
||||||
rotateElement(img, -90)
|
|
||||||
}
|
|
||||||
buttonContainer.appendChild(rotateCCW);
|
buttonContainer.appendChild(rotateCCW);
|
||||||
|
|
||||||
const rotateCW = document.createElement('button');
|
const rotateCW = document.createElement('button');
|
||||||
|
@ -164,15 +213,7 @@
|
||||||
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
|
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
|
||||||
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
|
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
|
||||||
</svg>`;
|
</svg>`;
|
||||||
rotateCW.onclick = e => {
|
rotateCW.onclick = rotateCWButtonCallback;
|
||||||
var imgContainer = e.target;
|
|
||||||
while (!imgContainer.classList.contains("page-container")) {
|
|
||||||
imgContainer = imgContainer.parentNode;
|
|
||||||
}
|
|
||||||
const img = imgContainer.querySelector("img");
|
|
||||||
|
|
||||||
rotateElement(img, 90)
|
|
||||||
}
|
|
||||||
buttonContainer.appendChild(rotateCW);
|
buttonContainer.appendChild(rotateCW);
|
||||||
|
|
||||||
const deletePage = document.createElement('button');
|
const deletePage = document.createElement('button');
|
||||||
|
@ -181,20 +222,32 @@
|
||||||
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6Z"/>
|
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6Z"/>
|
||||||
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1ZM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118ZM2.5 3h11V2h-11v1Z"/>
|
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1ZM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118ZM2.5 3h11V2h-11v1Z"/>
|
||||||
</svg>`;
|
</svg>`;
|
||||||
deletePage.onclick = e => {
|
deletePage.onclick = deletePageButtonCallback;
|
||||||
var imgContainer = e.target;
|
|
||||||
while (!imgContainer.classList.contains("page-container")) {
|
|
||||||
imgContainer = imgContainer.parentNode;
|
|
||||||
}
|
|
||||||
pagesContainer.removeChild(imgContainer);
|
|
||||||
}
|
|
||||||
buttonContainer.appendChild(deletePage);
|
buttonContainer.appendChild(deletePage);
|
||||||
|
|
||||||
div.appendChild(buttonContainer);
|
div.appendChild(buttonContainer);
|
||||||
|
|
||||||
|
const insertFileButtonContainer = document.createElement('div');
|
||||||
|
insertFileButtonContainer.classList.add("insert-file-button-container", "align-top");
|
||||||
|
|
||||||
|
const insertFileButton = document.createElement('button');
|
||||||
|
insertFileButton.classList.add("btn", "btn-primary", "insert-file-button", "align-center-right");
|
||||||
|
insertFileButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
|
||||||
|
<path d="M8 6.5a.5.5 0 0 1 .5.5v1.5H10a.5.5 0 0 1 0 1H8.5V11a.5.5 0 0 1-1 0V9.5H6a.5.5 0 0 1 0-1h1.5V7a.5.5 0 0 1 .5-.5z"/>
|
||||||
|
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
|
||||||
|
</svg>`;
|
||||||
|
insertFileButton.onclick = insertFileButtonCallback;
|
||||||
|
insertFileButtonContainer.appendChild(insertFileButton);
|
||||||
|
|
||||||
|
div.appendChild(insertFileButtonContainer);
|
||||||
|
|
||||||
|
if (nextSiblingElement) {
|
||||||
|
pagesContainer.insertBefore(div, nextSiblingElement);
|
||||||
|
} else {
|
||||||
pagesContainer.appendChild(div);
|
pagesContainer.appendChild(div);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function rotateElement(element, deg) {
|
function rotateElement(element, deg) {
|
||||||
var lastTransform = element.style.rotate;
|
var lastTransform = element.style.rotate;
|
||||||
|
@ -236,7 +289,7 @@
|
||||||
|
|
||||||
const downloadLink = document.createElement('a');
|
const downloadLink = document.createElement('a');
|
||||||
downloadLink.href = url;
|
downloadLink.href = url;
|
||||||
downloadLink.download = 'example.pdf';
|
downloadLink.download = fileName ? fileName : 'managed.pdf';
|
||||||
downloadLink.click(); // Simulate a click on the download link to start the download
|
downloadLink.click(); // Simulate a click on the download link to start the download
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,11 +297,6 @@
|
||||||
var objectUrl = URL.createObjectURL(file);
|
var objectUrl = URL.createObjectURL(file);
|
||||||
var pdfDocument = await toPdfLib(objectUrl);
|
var pdfDocument = await toPdfLib(objectUrl);
|
||||||
var renderer = await toRenderer(objectUrl);
|
var renderer = await toRenderer(objectUrl);
|
||||||
|
|
||||||
myDocument = pdfDocument;
|
|
||||||
myRenderer = renderer;
|
|
||||||
console.log(renderer, pdfDocument)
|
|
||||||
|
|
||||||
return { renderer, pdfDocument };
|
return { renderer, pdfDocument };
|
||||||
}
|
}
|
||||||
async function toPdfLib(objectUrl) {
|
async function toPdfLib(objectUrl) {
|
||||||
|
@ -330,6 +378,7 @@
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-container img {
|
.page-container img {
|
||||||
|
@ -341,7 +390,7 @@
|
||||||
top: 50%;
|
top: 50%;
|
||||||
translate: -50% -50%;
|
translate: -50% -50%;
|
||||||
box-shadow: 0 0 10px rgba(0,0,0);
|
box-shadow: 0 0 10px rgba(0,0,0);
|
||||||
transition: rotate .3s;
|
transition: rotate 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-container .button-container {
|
.page-container .button-container {
|
||||||
|
@ -359,13 +408,37 @@
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
.page-container:first-child .move-up-button {
|
.page-container:nth-child(2) .move-up-button {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
.page-container:last-child .move-down-button {
|
.page-container:last-child .move-down-button {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* "insert pdf" buttons that appear on the right when hover */
|
||||||
|
.insert-file-button-container {
|
||||||
|
translate: 0 -50%;
|
||||||
|
width: 100%;
|
||||||
|
height: 60px;
|
||||||
|
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
.insert-file-button-container:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.05s;
|
||||||
|
}
|
||||||
|
.insert-file-button {
|
||||||
|
translate: 100% -50%;
|
||||||
|
rotate: 45deg;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 100px 100px 100px 0;
|
||||||
|
}
|
||||||
|
.insert-file-button > * {
|
||||||
|
rotate: -45deg;
|
||||||
|
}
|
||||||
|
|
||||||
#add-pdf-button {
|
#add-pdf-button {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue