refactor: normalize files
This commit is contained in:
@@ -5,16 +5,16 @@ function showErrorBanner(message, stackTrace) {
|
||||
document.querySelector("#errorContainer p").textContent = message;
|
||||
document.querySelector("#traceContent").textContent = stackTrace;
|
||||
}
|
||||
let firstErrorOccurred = false;
|
||||
let firstErrorOccurred = false;
|
||||
|
||||
$(document).ready(function() {
|
||||
$('form').submit(async function(event) {
|
||||
event.preventDefault();
|
||||
firstErrorOccurred = false;
|
||||
firstErrorOccurred = false;
|
||||
const url = this.action;
|
||||
const files = $('#fileInput-input')[0].files;
|
||||
const formData = new FormData(this);
|
||||
|
||||
|
||||
// Remove empty file entries
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (value instanceof File && !value.name) {
|
||||
@@ -113,7 +113,7 @@ async function handleResponse(blob, filename, considerViewOptions = false, isZip
|
||||
const url = URL.createObjectURL(blob);
|
||||
window.open(url, '_blank');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!isZip){
|
||||
downloadFile(blob, filename);
|
||||
@@ -152,20 +152,20 @@ async function submitMultiPdfForm(url, files) {
|
||||
// Show the progress bar
|
||||
$('#progressBarContainer').show();
|
||||
// Initialize the progress bar
|
||||
|
||||
|
||||
let progressBar = $('#progressBar');
|
||||
progressBar.css('width', '0%');
|
||||
progressBar.attr('aria-valuenow', 0);
|
||||
progressBar.attr('aria-valuemax', files.length);
|
||||
|
||||
|
||||
if (zipFiles) {
|
||||
jszip = new JSZip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Get the form with the method attribute set to POST
|
||||
let postForm = document.querySelector('form[method="POST"]');
|
||||
|
||||
|
||||
// Get existing form data
|
||||
let formData;
|
||||
if (postForm) {
|
||||
@@ -191,11 +191,11 @@ async function submitMultiPdfForm(url, files) {
|
||||
const promises = chunk.map(async file => {
|
||||
let fileFormData = new FormData();
|
||||
fileFormData.append('fileInput', file);
|
||||
console.log(fileFormData);
|
||||
console.log(fileFormData);
|
||||
// Add other form data
|
||||
for (let pair of formData.entries()) {
|
||||
fileFormData.append(pair[0], pair[1]);
|
||||
console.log(pair[0]+ ', ' + pair[1]);
|
||||
console.log(pair[0]+ ', ' + pair[1]);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -213,7 +213,7 @@ async function submitMultiPdfForm(url, files) {
|
||||
}
|
||||
});
|
||||
await Promise.all(promises);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (zipFiles) {
|
||||
|
||||
@@ -120,7 +120,7 @@ const DraggableUtils = {
|
||||
newWidth = newWidth * scaleMultiplier;
|
||||
newHeight = newHeight * scaleMultiplier;
|
||||
}
|
||||
|
||||
|
||||
createdCanvas.style.width = newWidth+"px";
|
||||
createdCanvas.style.height = newHeight+"px";
|
||||
|
||||
@@ -147,7 +147,7 @@ const DraggableUtils = {
|
||||
if (!pagesMap) {
|
||||
pagesMap = {};
|
||||
}
|
||||
|
||||
|
||||
const elements = [...this.boxDragContainer.querySelectorAll(".draggable-canvas")];
|
||||
const draggablesData = elements.map(el => {return{element:el, offsetWidth:el.offsetWidth, offsetHeight:el.offsetHeight}});
|
||||
elements.forEach(el => this.boxDragContainer.removeChild(el));
|
||||
@@ -164,7 +164,7 @@ const DraggableUtils = {
|
||||
if (!pagesMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const draggablesData = pagesMap[this.pageIndex];
|
||||
if (draggablesData) {
|
||||
draggablesData.forEach(draggableData => this.boxDragContainer.appendChild(draggableData.element));
|
||||
@@ -177,7 +177,7 @@ const DraggableUtils = {
|
||||
this.pdfDoc = pdfDocument ? pdfDocument : this.pdfDoc;
|
||||
this.pageIndex = pageIdx;
|
||||
|
||||
// persist
|
||||
// persist
|
||||
const page = await this.pdfDoc.getPage(this.pageIndex+1);
|
||||
|
||||
// set the canvas size to the size of the page
|
||||
@@ -214,7 +214,7 @@ const DraggableUtils = {
|
||||
},
|
||||
|
||||
parseTransform(element) {
|
||||
|
||||
|
||||
},
|
||||
async getOverlayedPdfDocument() {
|
||||
const pdfBytes = await this.pdfDoc.getData();
|
||||
@@ -227,7 +227,7 @@ const DraggableUtils = {
|
||||
continue;
|
||||
}
|
||||
console.log(typeof pageIdx);
|
||||
|
||||
|
||||
const page = pdfDocModified.getPage(parseInt(pageIdx));
|
||||
const draggablesData = pagesMap[pageIdx];
|
||||
const offsetWidth = pagesMap[pageIdx+"-offsetWidth"];
|
||||
@@ -239,7 +239,7 @@ const DraggableUtils = {
|
||||
const response = await fetch(draggableElement.toDataURL());
|
||||
const draggableImgBytes = await response.arrayBuffer();
|
||||
const pdfImageObject = await pdfDocModified.embedPng(draggableImgBytes);
|
||||
|
||||
|
||||
// calculate the position in the pdf document
|
||||
const tansform = draggableElement.style.transform.replace(/[^.,-\d]/g, '');
|
||||
const transformComponents = tansform.split(",");
|
||||
@@ -261,7 +261,7 @@ const DraggableUtils = {
|
||||
width: draggablePositionRelative.width * page.getWidth(),
|
||||
height: draggablePositionRelative.height * page.getHeight(),
|
||||
}
|
||||
|
||||
|
||||
// draw the image
|
||||
page.drawImage(pdfImageObject, {
|
||||
x: draggablePositionPdf.x,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function updateFavoritesDropdown() {
|
||||
var dropdown = document.querySelector('#favoritesDropdown');
|
||||
|
||||
|
||||
// Check if dropdown exists
|
||||
if (!dropdown) {
|
||||
console.error('Dropdown element with ID "favoritesDropdown" not found!');
|
||||
|
||||
@@ -81,7 +81,7 @@ function setupFileInput(chooser) {
|
||||
document.body.addEventListener('drop', dropListener);
|
||||
|
||||
$("#" + elementId).on("change", function(e) {
|
||||
allFiles = Array.from(e.target.files);
|
||||
allFiles = Array.from(e.target.files);
|
||||
handleFileInputChange(this);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
function initializeGame() {
|
||||
const gameContainer = document.getElementById('game-container');
|
||||
const player = document.getElementById('player');
|
||||
|
||||
|
||||
let playerSize = gameContainer.clientWidth * 0.0625; // 5% of container width
|
||||
player.style.width = playerSize + 'px';
|
||||
player.style.height = playerSize + 'px';
|
||||
|
||||
|
||||
let playerX = gameContainer.clientWidth / 2 - playerSize / 2;
|
||||
let playerY = gameContainer.clientHeight * 0.1;
|
||||
const scoreElement = document.getElementById('score');
|
||||
@@ -18,12 +18,12 @@ function initializeGame() {
|
||||
let projectileHeight = gameContainer.clientHeight * 0.01667; // 1% of container height
|
||||
|
||||
let paused = false;
|
||||
|
||||
|
||||
const fireRate = 200; // Time between shots in milliseconds
|
||||
let lastProjectileTime = 0;
|
||||
let lives = 3;
|
||||
|
||||
|
||||
|
||||
|
||||
let highScore = localStorage.getItem('highScore') ? parseInt(localStorage.getItem('highScore')) : 0;
|
||||
updateHighScore();
|
||||
|
||||
@@ -195,7 +195,7 @@ function initializeGame() {
|
||||
score = 0;
|
||||
level = 1;
|
||||
lives = 3;
|
||||
|
||||
|
||||
gameOver = false;
|
||||
|
||||
updateScore();
|
||||
|
||||
@@ -7,7 +7,7 @@ function filterCards() {
|
||||
var card = cards[i];
|
||||
var title = card.querySelector('h5.card-title').innerText;
|
||||
var text = card.querySelector('p.card-text').innerText;
|
||||
|
||||
|
||||
// Get the navbar tags associated with the card
|
||||
var navbarItem = document.querySelector(`a.dropdown-item[href="${card.id}"]`);
|
||||
var navbarTags = navbarItem ? navbarItem.getAttribute('data-bs-tags') : '';
|
||||
|
||||
@@ -8,13 +8,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// Check if the dropdown contains the browser's language
|
||||
const dropdownLangExists = document.querySelector(`.lang_dropdown-item[data-language-code="${browserLang}"]`);
|
||||
|
||||
|
||||
// Set the default language to browser's language or 'en_GB' if not found in the dropdown
|
||||
const defaultLocale = dropdownLangExists ? browserLang : 'en_GB';
|
||||
const storedLocale = localStorage.getItem('languageCode') || defaultLocale;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const dropdownItems = document.querySelectorAll('.lang_dropdown-item');
|
||||
|
||||
for (let i = 0; i < dropdownItems.length; i++) {
|
||||
@@ -70,7 +70,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
element.remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//Sort languages by alphabet
|
||||
const list = Array.from(document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').children).filter(child => child.matches('a'));
|
||||
list.sort(function(a, b) {
|
||||
|
||||
@@ -9,7 +9,7 @@ document.getElementById("fileInput-input").addEventListener("change", function()
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {FileList} files
|
||||
* @param {FileList} files
|
||||
*/
|
||||
function displayFiles(files) {
|
||||
const list = document.getElementById("selectedFiles");
|
||||
|
||||
@@ -73,7 +73,7 @@ class DragDropManager {
|
||||
stopDraggingPage() {
|
||||
window.removeEventListener('mousemove', this.onDragEl);
|
||||
this.wrapper.classList.remove('drag-manager_dragging-container');
|
||||
this.wrapper.removeChild(this.endInsertionElement);
|
||||
this.wrapper.removeChild(this.endInsertionElement);
|
||||
window.removeEventListener('mouseup', this.stopDraggingPage)
|
||||
this.draggedImageEl = undefined;
|
||||
this.pageDragging = false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class PdfActionsManager {
|
||||
pageDirection;
|
||||
pageDirection;
|
||||
pagesContainer;
|
||||
|
||||
constructor(id) {
|
||||
@@ -23,7 +23,7 @@ class PdfActionsManager {
|
||||
|
||||
moveUpButtonCallback(e) {
|
||||
var imgContainer = this.getPageContainer(e.target);
|
||||
|
||||
|
||||
const sibling = imgContainer.previousSibling;
|
||||
if (sibling) {
|
||||
this.movePageTo(imgContainer, sibling, true);
|
||||
@@ -41,14 +41,14 @@ class PdfActionsManager {
|
||||
rotateCCWButtonCallback(e) {
|
||||
var imgContainer = this.getPageContainer(e.target);
|
||||
const img = imgContainer.querySelector("img");
|
||||
|
||||
|
||||
this.rotateElement(img, -90)
|
||||
};
|
||||
|
||||
rotateCWButtonCallback(e) {
|
||||
var imgContainer = this.getPageContainer(e.target);
|
||||
const img = imgContainer.querySelector("img");
|
||||
|
||||
|
||||
this.rotateElement(img, 90)
|
||||
};
|
||||
|
||||
@@ -93,7 +93,7 @@ class PdfActionsManager {
|
||||
const buttonContainer = document.createElement('div');
|
||||
|
||||
buttonContainer.classList.add("pdf-actions_button-container", "hide-on-drag");
|
||||
|
||||
|
||||
const moveUp = document.createElement('button');
|
||||
moveUp.classList.add("pdf-actions_move-left-button","btn", "btn-secondary");
|
||||
moveUp.innerHTML = `<i class="bi bi-arrow-${leftDirection}-short"></i>`;
|
||||
@@ -105,7 +105,7 @@ class PdfActionsManager {
|
||||
moveDown.innerHTML = `<i class="bi bi-arrow-${rightDirection}-short"></i>`;
|
||||
moveDown.onclick = this.moveDownButtonCallback;
|
||||
buttonContainer.appendChild(moveDown);
|
||||
|
||||
|
||||
const rotateCCW = document.createElement('button');
|
||||
rotateCCW.classList.add("btn", "btn-secondary");
|
||||
rotateCCW.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
|
||||
@@ -136,12 +136,12 @@ class PdfActionsManager {
|
||||
div.appendChild(buttonContainer);
|
||||
|
||||
const insertFileButtonContainer = document.createElement('div');
|
||||
|
||||
|
||||
insertFileButtonContainer.classList.add(
|
||||
"pdf-actions_insert-file-button-container",
|
||||
leftDirection,
|
||||
`align-center-${leftDirection}`);
|
||||
|
||||
|
||||
const insertFileButton = document.createElement('button');
|
||||
insertFileButton.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
|
||||
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">
|
||||
@@ -150,16 +150,16 @@ class PdfActionsManager {
|
||||
</svg>`;
|
||||
insertFileButton.onclick = this.insertFileButtonCallback;
|
||||
insertFileButtonContainer.appendChild(insertFileButton);
|
||||
|
||||
|
||||
div.appendChild(insertFileButtonContainer);
|
||||
|
||||
|
||||
// add this button to every element, but only show it on the last one :D
|
||||
const insertFileButtonRightContainer = document.createElement('div');
|
||||
insertFileButtonRightContainer.classList.add(
|
||||
"pdf-actions_insert-file-button-container",
|
||||
rightDirection,
|
||||
`align-center-${rightDirection}`);
|
||||
|
||||
|
||||
const insertFileButtonRight = document.createElement('button');
|
||||
insertFileButtonRight.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
|
||||
insertFileButtonRight.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">
|
||||
|
||||
@@ -1,285 +1,285 @@
|
||||
class PdfContainer {
|
||||
fileName;
|
||||
pagesContainer;
|
||||
pagesContainerWrapper;
|
||||
pdfAdapters;
|
||||
downloadLink;
|
||||
|
||||
constructor(id, wrapperId, pdfAdapters) {
|
||||
this.pagesContainer = document.getElementById(id)
|
||||
this.pagesContainerWrapper = document.getElementById(wrapperId);
|
||||
this.downloadLink = null;
|
||||
this.movePageTo = this.movePageTo.bind(this);
|
||||
this.addPdfs = this.addPdfs.bind(this);
|
||||
this.addPdfsFromFiles = this.addPdfsFromFiles.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.pdfAdapters = pdfAdapters;
|
||||
|
||||
this.pdfAdapters.forEach(adapter => {
|
||||
adapter.setActions({
|
||||
movePageTo: this.movePageTo,
|
||||
addPdfs: this.addPdfs,
|
||||
rotateElement: this.rotateElement,
|
||||
updateFilename: this.updateFilename
|
||||
})
|
||||
})
|
||||
|
||||
window.addPdfs = this.addPdfs;
|
||||
window.exportPdf = this.exportPdf;
|
||||
window.rotateAll = this.rotateAll;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
movePageTo(startElement, endElement, scrollTo = false) {
|
||||
const childArray = Array.from(this.pagesContainer.childNodes);
|
||||
const startIndex = childArray.indexOf(startElement);
|
||||
const endIndex = childArray.indexOf(endElement);
|
||||
this.pagesContainer.removeChild(startElement);
|
||||
if(!endElement) {
|
||||
this.pagesContainer.append(startElement);
|
||||
} else {
|
||||
this.pagesContainer.insertBefore(startElement, endElement);
|
||||
}
|
||||
|
||||
if(scrollTo) {
|
||||
const { width } = startElement.getBoundingClientRect();
|
||||
const vector = (endIndex !== -1 && startIndex > endIndex)
|
||||
? 0-width
|
||||
: width;
|
||||
|
||||
this.pagesContainerWrapper.scroll({
|
||||
left: this.pagesContainerWrapper.scrollLeft + vector,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
addPdfs(nextSiblingElement) {
|
||||
var input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.multiple = true;
|
||||
input.setAttribute("accept", "application/pdf");
|
||||
input.onchange = async(e) => {
|
||||
const files = e.target.files;
|
||||
|
||||
this.addPdfsFromFiles(files, nextSiblingElement);
|
||||
this.updateFilename(files ? files[0].name : "");
|
||||
}
|
||||
|
||||
input.click();
|
||||
}
|
||||
|
||||
async addPdfsFromFiles(files, nextSiblingElement) {
|
||||
this.fileName = files[0].name;
|
||||
for (var i=0; i < files.length; i++) {
|
||||
await this.addPdfFile(files[i], nextSiblingElement);
|
||||
}
|
||||
|
||||
document.querySelectorAll(".enable-on-file").forEach(element => {
|
||||
element.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
rotateElement(element, deg) {
|
||||
var lastTransform = element.style.rotate;
|
||||
if (!lastTransform) {
|
||||
lastTransform = "0";
|
||||
}
|
||||
const lastAngle = parseInt(lastTransform.replace(/[^\d-]/g, ''));
|
||||
const newAngle = lastAngle + deg;
|
||||
|
||||
element.style.rotate = newAngle + "deg";
|
||||
}
|
||||
|
||||
async addPdfFile(file, nextSiblingElement) {
|
||||
const { renderer, pdfDocument } = await this.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');
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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/pdf.worker.js'
|
||||
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) {
|
||||
for (var i=0; i<this.pagesContainer.childNodes.length; i++) {
|
||||
const img = this.pagesContainer.childNodes[i].querySelector("img");
|
||||
if (!img) continue;
|
||||
this.rotateElement(img, deg)
|
||||
}
|
||||
}
|
||||
|
||||
async exportPdf() {
|
||||
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++) {
|
||||
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
|
||||
if (!img) continue;
|
||||
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
|
||||
const page = pages[0];
|
||||
|
||||
const rotation = img.style.rotate;
|
||||
if (rotation) {
|
||||
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
|
||||
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
|
||||
}
|
||||
|
||||
pdfDoc.addPage(page);
|
||||
}
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(pdfBlob);
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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('.','');
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
export default PdfContainer;
|
||||
class PdfContainer {
|
||||
fileName;
|
||||
pagesContainer;
|
||||
pagesContainerWrapper;
|
||||
pdfAdapters;
|
||||
downloadLink;
|
||||
|
||||
constructor(id, wrapperId, pdfAdapters) {
|
||||
this.pagesContainer = document.getElementById(id)
|
||||
this.pagesContainerWrapper = document.getElementById(wrapperId);
|
||||
this.downloadLink = null;
|
||||
this.movePageTo = this.movePageTo.bind(this);
|
||||
this.addPdfs = this.addPdfs.bind(this);
|
||||
this.addPdfsFromFiles = this.addPdfsFromFiles.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.pdfAdapters = pdfAdapters;
|
||||
|
||||
this.pdfAdapters.forEach(adapter => {
|
||||
adapter.setActions({
|
||||
movePageTo: this.movePageTo,
|
||||
addPdfs: this.addPdfs,
|
||||
rotateElement: this.rotateElement,
|
||||
updateFilename: this.updateFilename
|
||||
})
|
||||
})
|
||||
|
||||
window.addPdfs = this.addPdfs;
|
||||
window.exportPdf = this.exportPdf;
|
||||
window.rotateAll = this.rotateAll;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
movePageTo(startElement, endElement, scrollTo = false) {
|
||||
const childArray = Array.from(this.pagesContainer.childNodes);
|
||||
const startIndex = childArray.indexOf(startElement);
|
||||
const endIndex = childArray.indexOf(endElement);
|
||||
this.pagesContainer.removeChild(startElement);
|
||||
if(!endElement) {
|
||||
this.pagesContainer.append(startElement);
|
||||
} else {
|
||||
this.pagesContainer.insertBefore(startElement, endElement);
|
||||
}
|
||||
|
||||
if(scrollTo) {
|
||||
const { width } = startElement.getBoundingClientRect();
|
||||
const vector = (endIndex !== -1 && startIndex > endIndex)
|
||||
? 0-width
|
||||
: width;
|
||||
|
||||
this.pagesContainerWrapper.scroll({
|
||||
left: this.pagesContainerWrapper.scrollLeft + vector,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
addPdfs(nextSiblingElement) {
|
||||
var input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.multiple = true;
|
||||
input.setAttribute("accept", "application/pdf");
|
||||
input.onchange = async(e) => {
|
||||
const files = e.target.files;
|
||||
|
||||
this.addPdfsFromFiles(files, nextSiblingElement);
|
||||
this.updateFilename(files ? files[0].name : "");
|
||||
}
|
||||
|
||||
input.click();
|
||||
}
|
||||
|
||||
async addPdfsFromFiles(files, nextSiblingElement) {
|
||||
this.fileName = files[0].name;
|
||||
for (var i=0; i < files.length; i++) {
|
||||
await this.addPdfFile(files[i], nextSiblingElement);
|
||||
}
|
||||
|
||||
document.querySelectorAll(".enable-on-file").forEach(element => {
|
||||
element.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
rotateElement(element, deg) {
|
||||
var lastTransform = element.style.rotate;
|
||||
if (!lastTransform) {
|
||||
lastTransform = "0";
|
||||
}
|
||||
const lastAngle = parseInt(lastTransform.replace(/[^\d-]/g, ''));
|
||||
const newAngle = lastAngle + deg;
|
||||
|
||||
element.style.rotate = newAngle + "deg";
|
||||
}
|
||||
|
||||
async addPdfFile(file, nextSiblingElement) {
|
||||
const { renderer, pdfDocument } = await this.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');
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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/pdf.worker.js'
|
||||
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) {
|
||||
for (var i=0; i<this.pagesContainer.childNodes.length; i++) {
|
||||
const img = this.pagesContainer.childNodes[i].querySelector("img");
|
||||
if (!img) continue;
|
||||
this.rotateElement(img, deg)
|
||||
}
|
||||
}
|
||||
|
||||
async exportPdf() {
|
||||
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++) {
|
||||
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
|
||||
if (!img) continue;
|
||||
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
|
||||
const page = pages[0];
|
||||
|
||||
const rotation = img.style.rotate;
|
||||
if (rotation) {
|
||||
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
|
||||
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
|
||||
}
|
||||
|
||||
pdfDoc.addPage(page);
|
||||
}
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(pdfBlob);
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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('.','');
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
export default PdfContainer;
|
||||
|
||||
@@ -17,7 +17,7 @@ const scrollDivHorizontally = (id) => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
divToScrollHorizontally.addEventListener("wheel", function(e) {
|
||||
e.preventDefault(); // prevent default mousewheel behavior
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,75 +1,75 @@
|
||||
// Toggle search bar when the search icon is clicked
|
||||
document.querySelector('#search-icon').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
var searchBar = document.querySelector('#navbarSearch');
|
||||
searchBar.classList.toggle('show');
|
||||
});
|
||||
window.onload = function() {
|
||||
var items = document.querySelectorAll('.dropdown-item, .nav-link');
|
||||
var dummyContainer = document.createElement('div');
|
||||
dummyContainer.style.position = 'absolute';
|
||||
dummyContainer.style.visibility = 'hidden';
|
||||
dummyContainer.style.whiteSpace = 'nowrap'; // Ensure we measure full width
|
||||
document.body.appendChild(dummyContainer);
|
||||
|
||||
var maxWidth = 0;
|
||||
|
||||
items.forEach(function(item) {
|
||||
var clone = item.cloneNode(true);
|
||||
dummyContainer.appendChild(clone);
|
||||
var width = clone.offsetWidth;
|
||||
if (width > maxWidth) {
|
||||
maxWidth = width;
|
||||
}
|
||||
dummyContainer.removeChild(clone);
|
||||
});
|
||||
|
||||
document.body.removeChild(dummyContainer);
|
||||
|
||||
// Store max width for later use
|
||||
window.navItemMaxWidth = maxWidth;
|
||||
};
|
||||
|
||||
// Show search results as user types in search box
|
||||
document.querySelector('#navbarSearchInput').addEventListener('input', function(e) {
|
||||
var searchText = e.target.value.toLowerCase();
|
||||
var items = document.querySelectorAll('.dropdown-item, .nav-link');
|
||||
var resultsBox = document.querySelector('#searchResults');
|
||||
|
||||
// Clear any previous results
|
||||
resultsBox.innerHTML = '';
|
||||
|
||||
items.forEach(function(item) {
|
||||
var titleElement = item.querySelector('.icon-text');
|
||||
var iconElement = item.querySelector('.icon');
|
||||
var itemHref = item.getAttribute('href');
|
||||
var tags = item.getAttribute('data-bs-tags') || ""; // If no tags, default to empty string
|
||||
|
||||
if (titleElement && iconElement && itemHref !== '#') {
|
||||
var title = titleElement.innerText;
|
||||
if ((title.toLowerCase().indexOf(searchText) !== -1 || tags.toLowerCase().indexOf(searchText) !== -1) && !resultsBox.querySelector(`a[href="${item.getAttribute('href')}"]`)) {
|
||||
var result = document.createElement('a');
|
||||
result.href = itemHref;
|
||||
result.classList.add('dropdown-item');
|
||||
|
||||
var resultIcon = document.createElement('img');
|
||||
resultIcon.src = iconElement.src;
|
||||
resultIcon.alt = 'icon';
|
||||
resultIcon.classList.add('icon');
|
||||
result.appendChild(resultIcon);
|
||||
|
||||
var resultText = document.createElement('span');
|
||||
resultText.textContent = title;
|
||||
resultText.classList.add('icon-text');
|
||||
result.appendChild(resultText);
|
||||
|
||||
resultsBox.appendChild(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Set the width of the search results box to the maximum width
|
||||
resultsBox.style.width = window.navItemMaxWidth + 'px';
|
||||
});
|
||||
|
||||
|
||||
// Toggle search bar when the search icon is clicked
|
||||
document.querySelector('#search-icon').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
var searchBar = document.querySelector('#navbarSearch');
|
||||
searchBar.classList.toggle('show');
|
||||
});
|
||||
window.onload = function() {
|
||||
var items = document.querySelectorAll('.dropdown-item, .nav-link');
|
||||
var dummyContainer = document.createElement('div');
|
||||
dummyContainer.style.position = 'absolute';
|
||||
dummyContainer.style.visibility = 'hidden';
|
||||
dummyContainer.style.whiteSpace = 'nowrap'; // Ensure we measure full width
|
||||
document.body.appendChild(dummyContainer);
|
||||
|
||||
var maxWidth = 0;
|
||||
|
||||
items.forEach(function(item) {
|
||||
var clone = item.cloneNode(true);
|
||||
dummyContainer.appendChild(clone);
|
||||
var width = clone.offsetWidth;
|
||||
if (width > maxWidth) {
|
||||
maxWidth = width;
|
||||
}
|
||||
dummyContainer.removeChild(clone);
|
||||
});
|
||||
|
||||
document.body.removeChild(dummyContainer);
|
||||
|
||||
// Store max width for later use
|
||||
window.navItemMaxWidth = maxWidth;
|
||||
};
|
||||
|
||||
// Show search results as user types in search box
|
||||
document.querySelector('#navbarSearchInput').addEventListener('input', function(e) {
|
||||
var searchText = e.target.value.toLowerCase();
|
||||
var items = document.querySelectorAll('.dropdown-item, .nav-link');
|
||||
var resultsBox = document.querySelector('#searchResults');
|
||||
|
||||
// Clear any previous results
|
||||
resultsBox.innerHTML = '';
|
||||
|
||||
items.forEach(function(item) {
|
||||
var titleElement = item.querySelector('.icon-text');
|
||||
var iconElement = item.querySelector('.icon');
|
||||
var itemHref = item.getAttribute('href');
|
||||
var tags = item.getAttribute('data-bs-tags') || ""; // If no tags, default to empty string
|
||||
|
||||
if (titleElement && iconElement && itemHref !== '#') {
|
||||
var title = titleElement.innerText;
|
||||
if ((title.toLowerCase().indexOf(searchText) !== -1 || tags.toLowerCase().indexOf(searchText) !== -1) && !resultsBox.querySelector(`a[href="${item.getAttribute('href')}"]`)) {
|
||||
var result = document.createElement('a');
|
||||
result.href = itemHref;
|
||||
result.classList.add('dropdown-item');
|
||||
|
||||
var resultIcon = document.createElement('img');
|
||||
resultIcon.src = iconElement.src;
|
||||
resultIcon.alt = 'icon';
|
||||
resultIcon.classList.add('icon');
|
||||
result.appendChild(resultIcon);
|
||||
|
||||
var resultText = document.createElement('span');
|
||||
resultText.textContent = title;
|
||||
resultText.classList.add('icon-text');
|
||||
result.appendChild(resultText);
|
||||
|
||||
resultsBox.appendChild(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Set the width of the search results box to the maximum width
|
||||
resultsBox.style.width = window.navItemMaxWidth + 'px';
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ TabContainer = {
|
||||
unloadedGroups.forEach(group => {
|
||||
const containers = group.querySelectorAll(".tab-container");
|
||||
const tabTitles = [...containers].map(c => c.getAttribute("title"));
|
||||
|
||||
|
||||
const tabList = document.createElement("div");
|
||||
tabList.classList.add("tab-buttons");
|
||||
tabTitles.forEach(title => {
|
||||
|
||||
Reference in New Issue
Block a user