Free PDF Editor Online

E-Sign PDF
100%

Tool Settings

No Tool Selected

Select an object on the page to edit it, or choose a tool from the toolbar above to add new elements.

Page 0 of 0 Zoom: 100%
Ready
`; const blob = new Blob(['\ufeff', html], { type: 'application/msword' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `edited_${timestamp}.doc`; link.click(); } elements.saveStatus.textContent = 'Download complete'; showToast('File downloaded successfully!', 'success'); } catch (error) { console.error('Download error:', error); showToast('Failed to generate file. Please try again.', 'error'); } finally { hideLoading(); } } // Legacy wrapper (still called by keyboard shortcut etc.) async function downloadEditedPDF() { openDownloadModal(); } // Print document function printDocument() { if (!pdfDocument) { showToast('Please load a PDF first.', 'error'); return; } // Create print window const printWindow = window.open('', '_blank'); printWindow.document.write(` Print PDF`); printWindow.document.write(''); printWindow.document.write(` `); // Add all pages as images document.querySelectorAll('.pdf-page').forEach(page => { const canvas = page.querySelector('canvas'); if (canvas) { const img = document.createElement('img'); img.src = canvas.toDataURL('image/png'); printWindow.document.body.appendChild(img); printWindow.document.body.appendChild(document.createElement('br')); } }); printWindow.document.write(''); printWindow.document.close(); printWindow.focus(); setTimeout(() => { printWindow.print(); printWindow.close(); }, 500); } // Keyboard shortcuts function handleKeyboardShortcuts(e) { // Don't trigger shortcuts when typing in input fields if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) { return; } // Ctrl+Z for undo if (e.ctrlKey && e.key === 'z' && !e.shiftKey) { e.preventDefault(); undoAction(); } // Ctrl+Shift+Z or Ctrl+Y for redo if ((e.ctrlKey && e.shiftKey && e.key === 'Z') || (e.ctrlKey && e.key === 'y')) { e.preventDefault(); redoAction(); } // Escape to deselect if (e.key === 'Escape') { deselectAll(); } } // Toast notifications function showToast(message, type = 'info') { const toastContainer = document.getElementById('toastContainer'); const toast = document.createElement('div'); toast.className = `toast ${type}`; let icon = 'ℹ️'; if (type === 'success') icon = '✅'; if (type === 'error') icon = '❌'; if (type === 'info') icon = 'ℹ️'; toast.innerHTML = ` ${icon} ${message} `; toastContainer.appendChild(toast); // Show toast setTimeout(() => { toast.classList.add('show'); }, 10); // Auto remove after 5 seconds setTimeout(() => { toast.classList.remove('show'); setTimeout(() => { toast.remove(); }, 300); }, 5000); } // Loading indicator function showLoading() { elements.loadingIndicator.classList.remove('hidden'); } function hideLoading() { elements.loadingIndicator.classList.add('hidden'); } // Initialize the application document.addEventListener('DOMContentLoaded', () => { initEventListeners(); // Setup intersection observer for automatic page selection during scroll const observerOptions = { root: document.querySelector('.pdf-container'), threshold: 0.6 }; window.pageObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const pageNum = parseInt(entry.target.dataset.page); if (pageNum && pageNum !== currentPage) { currentPage = pageNum; // Update info without scrolling to avoid jumpy behavior elements.currentPageInput.value = currentPage; elements.statusPage.textContent = currentPage; document.querySelectorAll('.page-thumbnail').forEach(thumb => { thumb.classList.remove('active'); if (parseInt(thumb.dataset.page) === currentPage) { thumb.classList.add('active'); } }); document.querySelectorAll('.pdf-page').forEach(page => { page.classList.remove('selected-page'); if (parseInt(page.dataset.page) === currentPage) { page.classList.add('selected-page'); } }); } } }); }, observerOptions); // Set initial tool selectTool('select'); // Show upload modal initially elements.uploadModal.classList.remove('hidden'); // Initialize settings display document.getElementById('fontSizeValue').textContent = document.getElementById('fontSize').value; document.getElementById('highlightOpacityValue').textContent = `${document.getElementById('highlightOpacity').value}%`; document.getElementById('borderWidthValue').textContent = `${document.getElementById('borderWidth').value}px`; document.getElementById('watermarkOpacityValue').textContent = `${elements.watermarkOpacity.value}%`; document.getElementById('watermarkSizeValue').textContent = `${elements.watermarkSize.value}px`; document.getElementById('imageOpacityValue').textContent = `${elements.imageOpacity.value}%`; document.getElementById('eraserSizeValue').textContent = `${elements.eraserSize.value}px`; // Update undo/redo buttons updateUndoRedoButtons(); // Set up tooltips setupTooltips(); // Initial save state saveState(); }); // Setup tooltips function setupTooltips() { const tooltips = { selectTool: 'Select and move annotations', textTool: 'Add text boxes', highlightTool: 'Highlight areas', imageTool: 'Add images', eraserTool: 'Delete annotations', signatureTool: 'Add signature', undoBtn: 'Undo (Ctrl+Z)', redoBtn: 'Redo (Ctrl+Shift+Z)', printBtn: 'Print document', downloadBtn: 'Download edited PDF', watermarkTool: 'Add watermark', findBtn: 'Find text in annotations' }; Object.keys(tooltips).forEach(id => { const element = document.getElementById(id); if (element) { element.title = tooltips[id]; } }); }