CoolFace
Apppublic

KEXEL/git

sourceHugging Faceupdated 1mo agoView on Hugging Face
0likes
pdfeditor.html746 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en">3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>Advanced PDF Editor</title>7    <script src="https://cdn.tailwindcss.com"></script>8    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>9    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>10    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">11    <style>12        .pdf-container {13            position: relative;14            overflow: auto;15            border: 1px solid #e5e7eb;16            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);17        }18        .canvas-container {19            margin: 0 auto;20            text-align: center;21            position: relative;22        }23        .annotation {24            position: absolute;25            border: 2px dashed #3b82f6;26            background-color: rgba(59, 130, 246, 0.2);27            cursor: move;28        }29        .annotation.selected {30            border: 2px solid #ef4444;31            z-index: 100;32        }33        .annotation-text {34            width: 100%;35            height: 100%;36            padding: 5px;37            resize: none;38            background: transparent;39            border: none;40            outline: none;41            font-family: Arial, sans-serif;42        }43        .tooltip {44            position: absolute;45            background: #1f2937;46            color: white;47            padding: 4px 8px;48            border-radius: 4px;49            font-size: 12px;50            opacity: 0;51            transition: opacity 0.2s;52            pointer-events: none;53            z-index: 1000;54        }55        .tooltip.active {56            opacity: 0.9;57        }58        @keyframes pulse {59            0%, 100% { opacity: 1; }60            50% { opacity: 0.5; }61        }62        .pulse {63            animation: pulse 1.5s infinite;64        }65    </style>66</head>67<body class="bg-gray-50 min-h-screen">68    <div class="container mx-auto px-4 py-8">69        <header class="mb-8">70            <h1 class="text-3xl font-bold text-gray-800 flex items-center">71                <i class="fas fa-file-pdf text-red-500 mr-3"></i>72                Advanced PDF Editor73            </h1>74            <p class="text-gray-600 mt-2">Upload, annotate, and modify your PDF documents with ease</p>75        </header>76 77        <div class="grid grid-cols-1 lg:grid-cols-4 gap-6">78            <!-- Tools Panel -->79            <div class="bg-white rounded-lg shadow p-4 lg:col-span-1">80                <h2 class="text-lg font-semibold text-gray-700 mb-4 flex items-center">81                    <i class="fas fa-tools mr-2"></i> Tools82                </h2>83                84                <div class="space-y-4">85                    <div>86                        <label class="block text-sm font-medium text-gray-700 mb-1">Upload PDF</label>87                        <div class="relative">88                            <input type="file" id="pdf-upload" accept=".pdf" class="hidden">89                            <label for="pdf-upload" class="w-full bg-blue-50 hover:bg-blue-100 text-blue-700 py-2 px-4 rounded border border-blue-200 flex items-center justify-center cursor-pointer transition">90                                <i class="fas fa-cloud-upload-alt mr-2"></i>91                                Choose File92                            </label>93                            <div id="file-name" class="text-xs text-gray-500 mt-1 truncate"></div>94                        </div>95                    </div>96 97                    <div class="pt-2 border-t border-gray-200">98                        <label class="block text-sm font-medium text-gray-700 mb-2">Annotation Tools</label>99                        <div class="grid grid-cols-3 gap-2">100                            <button id="text-tool" class="bg-gray-100 hover:bg-gray-200 text-gray-800 py-2 px-3 rounded flex flex-col items-center justify-center tool-btn active" data-tool="text">101                                <i class="fas fa-font mb-1"></i>102                                <span class="text-xs">Text</span>103                            </button>104                            <button id="highlight-tool" class="bg-gray-100 hover:bg-gray-200 text-gray-800 py-2 px-3 rounded flex flex-col items-center justify-center tool-btn" data-tool="highlight">105                                <i class="fas fa-highlighter mb-1"></i>106                                <span class="text-xs">Highlight</span>107                            </button>108                            <button id="rectangle-tool" class="bg-gray-100 hover:bg-gray-200 text-gray-800 py-2 px-3 rounded flex flex-col items-center justify-center tool-btn" data-tool="rectangle">109                                <i class="fas fa-square mb-1"></i>110                                <span class="text-xs">Rectangle</span>111                            </button>112                            <button id="freehand-tool" class="bg-gray-100 hover:bg-gray-200 text-gray-800 py-2 px-3 rounded flex flex-col items-center justify-center tool-btn" data-tool="freehand">113                                <i class="fas fa-pen mb-1"></i>114                                <span class="text-xs">Freehand</span>115                            </button>116                            <button id="stamp-tool" class="bg-gray-100 hover:bg-gray-200 text-gray-800 py-2 px-3 rounded flex flex-col items-center justify-center tool-btn" data-tool="stamp">117                                <i class="fas fa-stamp mb-1"></i>118                                <span class="text-xs">Stamp</span>119                            </button>120                            <button id="eraser-tool" class="bg-gray-100 hover:bg-gray-200 text-gray-800 py-2 px-3 rounded flex flex-col items-center justify-center tool-btn" data-tool="eraser">121                                <i class="fas fa-eraser mb-1"></i>122                                <span class="text-xs">Eraser</span>123                            </button>124                        </div>125                    </div>126 127                    <div class="pt-2 border-t border-gray-200">128                        <label class="block text-sm font-medium text-gray-700 mb-2">Properties</label>129                        <div class="space-y-3">130                            <div>131                                <label class="block text-xs text-gray-600 mb-1">Color</label>132                                <input type="color" id="color-picker" value="#3b82f6" class="w-full h-8 cursor-pointer">133                            </div>134                            <div>135                                <label class="block text-xs text-gray-600 mb-1">Opacity</label>136                                <input type="range" id="opacity-slider" min="10" max="100" value="50" class="w-full">137                            </div>138                            <div>139                                <label class="block text-xs text-gray-600 mb-1">Font Size</label>140                                <select id="font-size" class="w-full border border-gray-200 rounded p-1 text-sm">141                                    <option value="12">12px</option>142                                    <option value="14">14px</option>143                                    <option value="16" selected>16px</option>144                                    <option value="18">18px</option>145                                    <option value="20">20px</option>146                                    <option value="24">24px</option>147                                </select>148                            </div>149                        </div>150                    </div>151 152                    <div class="pt-2 border-t border-gray-200">153                        <label class="block text-sm font-medium text-gray-700 mb-2">Pages</label>154                        <div id="page-thumbnails" class="space-y-2 max-h-40 overflow-y-auto">155                            <div class="text-center text-gray-500 py-4">156                                <i class="fas fa-file-upload text-2xl mb-2"></i>157                                <p class="text-sm">Upload a PDF to view pages</p>158                            </div>159                        </div>160                    </div>161                </div>162            </div>163 164            <!-- Main Editor Area -->165            <div class="bg-white rounded-lg shadow p-4 lg:col-span-3">166                <div class="flex justify-between items-center mb-4">167                    <h2 class="text-lg font-semibold text-gray-700 flex items-center">168                        <i class="fas fa-edit mr-2"></i> Editor169                    </h2>170                    <div class="flex space-x-2">171                        <button id="zoom-in" class="bg-gray-100 hover:bg-gray-200 text-gray-800 p-2 rounded">172                            <i class="fas fa-search-plus"></i>173                        </button>174                        <button id="zoom-out" class="bg-gray-100 hover:bg-gray-200 text-gray-800 p-2 rounded">175                            <i class="fas fa-search-minus"></i>176                        </button>177                        <button id="download-pdf" class="bg-blue-50 hover:bg-blue-100 text-blue-700 py-2 px-4 rounded border border-blue-200 flex items-center">178                            <i class="fas fa-file-download mr-2"></i>179                            Download180                        </button>181                    </div>182                </div>183 184                <div id="pdf-container" class="pdf-container h-[70vh] bg-gray-100 rounded-lg flex items-center justify-center">185                    <div id="pdf-placeholder" class="text-center p-8">186                        <i class="fas fa-file-pdf text-5xl text-gray-300 mb-4"></i>187                        <h3 class="text-xl font-medium text-gray-500 mb-2">No PDF Loaded</h3>188                        <p class="text-gray-400 mb-4">Upload a PDF file to start editing</p>189                        <label for="pdf-upload" class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-6 rounded cursor-pointer inline-block">190                            <i class="fas fa-cloud-upload-alt mr-2"></i>191                            Select PDF File192                        </label>193                    </div>194                    <div id="pdf-viewer" class="hidden w-full h-full relative overflow-auto">195                        <div id="canvas-container" class="canvas-container"></div>196                    </div>197                </div>198 199                <div class="mt-4 flex justify-between items-center">200                    <div class="flex items-center space-x-4">201                        <button id="prev-page" class="bg-gray-100 hover:bg-gray-200 text-gray-800 p-2 rounded disabled:opacity-50" disabled>202                            <i class="fas fa-chevron-left"></i>203                        </button>204                        <span id="page-info" class="text-sm text-gray-600">Page: 0/0</span>205                        <button id="next-page" class="bg-gray-100 hover:bg-gray-200 text-gray-800 p-2 rounded disabled:opacity-50" disabled>206                            <i class="fas fa-chevron-right"></i>207                        </button>208                    </div>209                    <div class="text-sm text-gray-500">210                        <span id="zoom-level">100%</span>211                    </div>212                </div>213            </div>214        </div>215 216        <div class="mt-8 bg-white rounded-lg shadow p-4">217            <h2 class="text-lg font-semibold text-gray-700 mb-4 flex items-center">218                <i class="fas fa-history mr-2"></i> Recent Actions219            </h2>220            <div id="action-history" class="text-sm text-gray-600">221                <div class="text-center text-gray-400 py-4">222                    <i class="fas fa-info-circle mr-1"></i>223                    No actions recorded yet224                </div>225            </div>226        </div>227    </div>228 229    <div id="tooltip" class="tooltip"></div>230 231    <script>232        // Initialize PDF.js233        pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js';234        235        // Variables236        let pdfDoc = null;237        let pageNum = 1;238        let pageRendering = false;239        let pageNumPending = null;240        let scale = 1.0;241        let canvas = null;242        let ctx = null;243        let currentTool = 'text';244        let annotations = [];245        let selectedAnnotation = null;246        let isDragging = false;247        let startX, startY;248        let currentPage = 1;249        let pdfName = '';250        let actionHistory = [];251        252        // DOM Elements253        const pdfUpload = document.getElementById('pdf-upload');254        const pdfViewer = document.getElementById('pdf-viewer');255        const pdfPlaceholder = document.getElementById('pdf-placeholder');256        const canvasContainer = document.getElementById('canvas-container');257        const pageInfo = document.getElementById('page-info');258        const prevPage = document.getElementById('prev-page');259        const nextPage = document.getElementById('next-page');260        const zoomIn = document.getElementById('zoom-in');261        const zoomOut = document.getElementById('zoom-out');262        const zoomLevel = document.getElementById('zoom-level');263        const downloadPdf = document.getElementById('download-pdf');264        const toolButtons = document.querySelectorAll('.tool-btn');265        const colorPicker = document.getElementById('color-picker');266        const opacitySlider = document.getElementById('opacity-slider');267        const fontSizeSelect = document.getElementById('font-size');268        const pageThumbnails = document.getElementById('page-thumbnails');269        const actionHistoryContainer = document.getElementById('action-history');270        const fileNameDisplay = document.getElementById('file-name');271        const tooltip = document.getElementById('tooltip');272        273        // Event Listeners274        pdfUpload.addEventListener('change', handleFileSelect);275        prevPage.addEventListener('click', onPrevPage);276        nextPage.addEventListener('click', onNextPage);277        zoomIn.addEventListener('click', () => changeZoom(0.2));278        zoomOut.addEventListener('click', () => changeZoom(-0.2));279        downloadPdf.addEventListener('click', downloadModifiedPdf);280        281        // Tool buttons282        toolButtons.forEach(button => {283            button.addEventListener('click', () => {284                toolButtons.forEach(btn => btn.classList.remove('active', 'bg-blue-100', 'border-blue-300'));285                button.classList.add('active', 'bg-blue-100', 'border-blue-300');286                currentTool = button.dataset.tool;287                addActionToHistory(`Switched to ${button.dataset.tool} tool`);288            });289        });290        291        // Initialize first tool as active292        document.getElementById('text-tool').classList.add('active', 'bg-blue-100', 'border-blue-300');293        294        // Functions295        function handleFileSelect(event) {296            const file = event.target.files[0];297            if (file && file.type === 'application/pdf') {298                pdfName = file.name;299                fileNameDisplay.textContent = file.name;300                301                const fileReader = new FileReader();302                fileReader.onload = function() {303                    const typedArray = new Uint8Array(this.result);304                    loadPdf(typedArray);305                };306                fileReader.readAsArrayBuffer(file);307                308                addActionToHistory(`Uploaded PDF: ${file.name}`);309            } else {310                alert('Please select a valid PDF file.');311            }312        }313        314        function loadPdf(data) {315            pdfjsLib.getDocument(data).promise.then(function(pdfDoc_) {316                pdfDoc = pdfDoc_;317                pageInfo.textContent = `Page: 1/${pdfDoc.numPages}`;318                319                // Enable/disable buttons320                prevPage.disabled = true;321                nextPage.disabled = pdfDoc.numPages <= 1;322                323                // Show PDF viewer and hide placeholder324                pdfViewer.classList.remove('hidden');325                pdfPlaceholder.classList.add('hidden');326                327                // Render first page328                renderPage(1);329                330                // Generate thumbnails331                generateThumbnails();332            }).catch(function(error) {333                console.error('Error loading PDF:', error);334                alert('Error loading PDF. Please try another file.');335            });336        }337        338        function renderPage(num) {339            pageRendering = true;340            currentPage = num;341            342            // Update page display343            pageInfo.textContent = `Page: ${num}/${pdfDoc.numPages}`;344            345            // Update button states346            prevPage.disabled = num <= 1;347            nextPage.disabled = num >= pdfDoc.numPages;348            349            // Clear previous canvas350            canvasContainer.innerHTML = '';351            352            // Create new canvas353            canvas = document.createElement('canvas');354            canvas.className = 'pdf-page';355            canvasContainer.appendChild(canvas);356            ctx = canvas.getContext('2d');357            358            // Get page359            pdfDoc.getPage(num).then(function(page) {360                const viewport = page.getViewport({ scale: scale });361                canvas.height = viewport.height;362                canvas.width = viewport.width;363                364                // Render PDF page into canvas context365                const renderContext = {366                    canvasContext: ctx,367                    viewport: viewport368                };369                370                const renderTask = page.render(renderContext);371                372                renderTask.promise.then(function() {373                    pageRendering = false;374                    if (pageNumPending !== null) {375                        renderPage(pageNumPending);376                        pageNumPending = null;377                    }378                    379                    // Render annotations for this page380                    renderAnnotations();381                });382            });383            384            // Highlight current page in thumbnails385            highlightCurrentThumbnail(num);386        }387        388        function onPrevPage() {389            if (pageNum <= 1) {390                return;391            }392            pageNum--;393            queueRenderPage(pageNum);394            addActionToHistory(`Navigated to page ${pageNum}`);395        }396        397        function onNextPage() {398            if (pageNum >= pdfDoc.numPages) {399                return;400            }401            pageNum++;402            queueRenderPage(pageNum);403            addActionToHistory(`Navigated to page ${pageNum}`);404        }405        406        function queueRenderPage(num) {407            if (pageRendering) {408                pageNumPending = num;409            } else {410                renderPage(num);411            }412        }413        414        function changeZoom(delta) {415            const newScale = scale + delta;416            if (newScale >= 0.2 && newScale <= 3.0) {417                scale = newScale;418                zoomLevel.textContent = `${Math.round(scale * 100)}%`;419                queueRenderPage(pageNum);420                addActionToHistory(`Zoom changed to ${Math.round(scale * 100)}%`);421            }422        }423        424        function generateThumbnails() {425            pageThumbnails.innerHTML = '';426            427            for (let i = 1; i <= pdfDoc.numPages; i++) {428                const thumbContainer = document.createElement('div');429                thumbContainer.className = 'relative cursor-pointer group';430                thumbContainer.dataset.page = i;431                432                const thumbCanvas = document.createElement('canvas');433                thumbCanvas.className = 'border border-gray-200 w-full';434                435                const pageNum = document.createElement('div');436                pageNum.className = 'absolute bottom-1 right-1 bg-black bg-opacity-50 text-white text-xs px-1 rounded';437                pageNum.textContent = i;438                439                thumbContainer.appendChild(thumbCanvas);440                thumbContainer.appendChild(pageNum);441                442                // Render thumbnail443                pdfDoc.getPage(i).then(function(page) {444                    const viewport = page.getViewport(0.2);445                    thumbCanvas.height = viewport.height;446                    thumbCanvas.width = viewport.width;447                    448                    page.render({449                        canvasContext: thumbCanvas.getContext('2d'),450                        viewport: viewport451                    });452                });453                454                // Click event to navigate to page455                thumbContainer.addEventListener('click', function() {456                    pageNum = parseInt(this.dataset.page);457                    queueRenderPage(pageNum);458                    addActionToHistory(`Navigated to page ${pageNum} via thumbnail`);459                });460                461                // Hover effect462                thumbContainer.addEventListener('mouseenter', function() {463                    this.classList.add('ring-2', 'ring-blue-400');464                });465                466                thumbContainer.addEventListener('mouseleave', function() {467                    if (parseInt(this.dataset.page) !== currentPage) {468                        this.classList.remove('ring-2', 'ring-blue-400');469                    }470                });471                472                pageThumbnails.appendChild(thumbContainer);473            }474        }475        476        function highlightCurrentThumbnail(pageNum) {477            const thumbs = pageThumbnails.querySelectorAll('[data-page]');478            thumbs.forEach(thumb => {479                if (parseInt(thumb.dataset.page) === pageNum) {480                    thumb.classList.add('ring-2', 'ring-blue-500');481                } else {482                    thumb.classList.remove('ring-2', 'ring-blue-500');483                }484            });485        }486        487        // Annotation functions488        function renderAnnotations() {489            // Clear existing annotations490            const existingAnnotations = canvasContainer.querySelectorAll('.annotation');491            existingAnnotations.forEach(ann => ann.remove());492            493            // Filter annotations for current page494            const pageAnnotations = annotations.filter(ann => ann.page === currentPage);495            496            // Render each annotation497            pageAnnotations.forEach(annotation => {498                const annElement = document.createElement('div');499                annElement.className = 'annotation';500                annElement.dataset.id = annotation.id;501                502                // Position and size503                annElement.style.left = `${annotation.x}px`;504                annElement.style.top = `${annotation.y}px`;505                annElement.style.width = `${annotation.width}px`;506                annElement.style.height = `${annotation.height}px`;507                508                // Style based on type509                if (annotation.type === 'text') {510                    const textarea = document.createElement('textarea');511                    textarea.className = 'annotation-text';512                    textarea.value = annotation.content || '';513                    textarea.style.color = annotation.color;514                    textarea.style.fontSize = `${annotation.fontSize}px`;515                    textarea.style.opacity = annotation.opacity / 100;516                    517                    // Update annotation content when text changes518                    textarea.addEventListener('input', function() {519                        const ann = annotations.find(a => a.id === annotation.id);520                        if (ann) ann.content = this.value;521                    });522                    523                    annElement.appendChild(textarea);524                } else if (annotation.type === 'highlight') {525                    annElement.style.backgroundColor = annotation.color;526                    annElement.style.opacity = annotation.opacity / 100;527                } else if (annotation.type === 'rectangle') {528                    annElement.style.border = `2px solid ${annotation.color}`;529                    annElement.style.backgroundColor = 'transparent';530                }531                532                // Selection533                if (selectedAnnotation && selectedAnnotation.id === annotation.id) {534                    annElement.classList.add('selected');535                }536                537                // Event listeners for interaction538                annElement.addEventListener('mousedown', startAnnotationDrag);539                annElement.addEventListener('mouseup', stopAnnotationDrag);540                annElement.addEventListener('dblclick', deleteAnnotation);541                542                canvasContainer.appendChild(annElement);543            });544        }545        546        function createAnnotation(e) {547            if (!canvas || currentTool === 'eraser') return;548            549            const rect = canvas.getBoundingClientRect();550            const x = e.clientX - rect.left;551            const y = e.clientY - rect.top;552            553            const newAnnotation = {554                id: Date.now().toString(),555                type: currentTool,556                page: currentPage,557                x: x,558                y: y,559                width: currentTool === 'text' ? 200 : 100,560                height: currentTool === 'text' ? 50 : 30,561                color: colorPicker.value,562                opacity: opacitySlider.value,563                fontSize: fontSizeSelect.value,564                content: ''565            };566            567            annotations.push(newAnnotation);568            selectedAnnotation = newAnnotation;569            570            renderAnnotations();571            572            // Focus textarea if it's a text annotation573            if (currentTool === 'text') {574                setTimeout(() => {575                    const textarea = canvasContainer.querySelector('.annotation.selected textarea');576                    if (textarea) textarea.focus();577                }, 10);578            }579            580            addActionToHistory(`Added ${currentTool} annotation`);581        }582        583        function startAnnotationDrag(e) {584            if (e.target.tagName === 'TEXTAREA') return;585            586            e.preventDefault();587            e.stopPropagation();588            589            const annotationId = e.currentTarget.dataset.id;590            selectedAnnotation = annotations.find(ann => ann.id === annotationId);591            592            // Update all annotations to show selected state593            renderAnnotations();594            595            // Start drag596            isDragging = true;597            startX = e.clientX;598            startY = e.clientY;599            600            document.addEventListener('mousemove', dragAnnotation);601            document.addEventListener('mouseup', stopAnnotationDrag);602        }603        604        function dragAnnotation(e) {605            if (!isDragging || !selectedAnnotation) return;606            607            const rect = canvas.getBoundingClientRect();608            const dx = e.clientX - startX;609            const dy = e.clientY - startY;610            611            selectedAnnotation.x += dx;612            selectedAnnotation.y += dy;613            614            startX = e.clientX;615            startY = e.clientY;616            617            renderAnnotations();618        }619        620        function stopAnnotationDrag() {621            isDragging = false;622            document.removeEventListener('mousemove', dragAnnotation);623            document.removeEventListener('mouseup', stopAnnotationDrag);624            625            if (selectedAnnotation) {626                addActionToHistory(`Moved ${selectedAnnotation.type} annotation`);627            }628        }629        630        function deleteAnnotation(e) {631            e.stopPropagation();632            633            const annotationId = e.currentTarget.dataset.id;634            const annotationIndex = annotations.findIndex(ann => ann.id === annotationId);635            636            if (annotationIndex !== -1) {637                const deletedAnnotation = annotations[annotationIndex];638                annotations.splice(annotationIndex, 1);639                selectedAnnotation = null;640                641                renderAnnotations();642                addActionToHistory(`Deleted ${deletedAnnotation.type} annotation`);643            }644        }645        646        // Canvas click handler for creating new annotations647        canvasContainer.addEventListener('mousedown', function(e) {648            if (e.target === canvasContainer || e.target === canvas) {649                createAnnotation(e);650            }651        });652        653        // Tooltip handling654        document.querySelectorAll('[data-tooltip]').forEach(el => {655            el.addEventListener('mouseenter', function() {656                const tooltipText = this.dataset.tooltip;657                tooltip.textContent = tooltipText;658                tooltip.classList.add('active');659                660                const rect = this.getBoundingClientRect();661                tooltip.style.left = `${rect.left + rect.width / 2 - tooltip.offsetWidth / 2}px`;662                tooltip.style.top = `${rect.top - tooltip.offsetHeight - 5}px`;663            });664            665            el.addEventListener('mouseleave', function() {666                tooltip.classList.remove('active');667            });668        });669        670        // Download modified PDF671        function downloadModifiedPdf() {672            if (!pdfDoc) {673                alert('No PDF loaded');674                return;675            }676            677            addActionToHistory('Initiated PDF download');678            679            // In a real implementation, you would use jsPDF or similar to create a new PDF680            // with the annotations. This is a simplified version that just alerts.681            682            alert('In a full implementation, this would download the modified PDF with all annotations.');683            684            // For demonstration, we'll create a simple download of the original file685            if (pdfUpload.files.length > 0) {686                const file = pdfUpload.files[0];687                const url = URL.createObjectURL(file);688                689                const a = document.createElement('a');690                a.href = url;691                a.download = `modified_${file.name}`;692                document.body.appendChild(a);693                a.click();694                695                setTimeout(() => {696                    document.body.removeChild(a);697                    URL.revokeObjectURL(url);698                }, 0);699            }700        }701        702        // Action history703        function addActionToHistory(action) {704            const timestamp = new Date().toLocaleTimeString();705            actionHistory.unshift({ action, timestamp });706            707            if (actionHistory.length > 10) {708                actionHistory.pop();709            }710            711            updateActionHistoryDisplay();712        }713        714        function updateActionHistoryDisplay() {715            if (actionHistory.length === 0) {716                actionHistoryContainer.innerHTML = `717                    <div class="text-center text-gray-400 py-4">718                        <i class="fas fa-info-circle mr-1"></i>719                        No actions recorded yet720                    </div>721                `;722                return;723            }724            725            actionHistoryContainer.innerHTML = '';726            727            actionHistory.forEach(item => {728                const actionElement = document.createElement('div');729                actionElement.className = 'flex justify-between items-center py-2 border-b border-gray-100';730                731                const actionText = document.createElement('span');732                actionText.textContent = item.action;733                actionText.className = 'text-gray-700';734                735                const actionTime = document.createElement('span');736                actionTime.textContent = item.timestamp;737                actionTime.className = 'text-gray-500 text-xs';738                739                actionElement.appendChild(actionText);740                actionElement.appendChild(actionTime);741                actionHistoryContainer.appendChild(actionElement);742            });743        }744    </script>745</body>746</html>