# easy-invoice/2.1.0/assets/js/document-pdf.js

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.1.0. 215 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.1.0/code/assets/js/document-pdf.js
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.1.0/raw/assets/js/document-pdf.js
- Modified: 2025-08-19T12:00:36+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/easy-invoice/2.1.0/code/assets/js/document-pdf.js#L10-L20`.

```javascript
/**
 * Easy Invoice Document PDF Generation using html2canvas
 * Generates PDF from the actual rendered invoice/quote HTML
 * 
 * @package Easy_Invoice
 * @version 1.0.0
 */

(function() {
    'use strict';

    // Global Document PDF Generator Class
    window.DocumentPdfGenerator = class DocumentPdfGenerator {
        constructor(documentType = 'invoice') {
            this.documentType = documentType; // 'invoice' or 'quote'
            this.init();
        }

        init() {
            // Add html2canvas script if not already loaded
            if (typeof html2canvas === 'undefined') {
                this.loadScript('https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js', () => {
                    this.loadScript('https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js', () => {
                        this.setupPDFButtons();
                    });
                });
            } else {
                this.setupPDFButtons();
            }
        }

        loadScript(src, callback) {
            const script = document.createElement('script');
            script.src = src;
            script.onload = callback;
            document.head.appendChild(script);
        }

        setupPDFButtons() {
            // Find all PDF download buttons
            const pdfButtons = document.querySelectorAll('.download-pdf-btn, .ei-download-pdf');
            
            pdfButtons.forEach(button => {
                button.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.generatePDF();
                });
            });
        }

        async generatePDF() {
            try {
                // Show loading state
                this.showLoading();
                
                // Find the document content
                const documentContent = document.querySelector('.invoice-content') || 
                                      document.querySelector('.quote-content');
                
                if (!documentContent) {
                    throw new Error('Document content not found');
                }

                // Get document data for filename
                const documentTitle = document.querySelector('.invoice-title')?.textContent || 
                                    document.querySelector('.quote-title')?.textContent || 
                                    this.documentType;
                const documentNumber = document.querySelector('.invoice-number')?.textContent || 
                                     document.querySelector('.quote-number')?.textContent || 
                                     '';
                const filename = `${documentTitle}-${documentNumber}-${new Date().toISOString().split('T')[0]}.pdf`;

                // Simple html2canvas configuration
                const canvas = await html2canvas(documentContent, {
                    scale: 1.5,
                    useCORS: true,
                    allowTaint: true,
                    backgroundColor: '#ffffff',
                    logging: false
                });

                // Convert canvas to image
                const imgData = canvas.toDataURL('image/jpeg');
                
                // Create PDF
                const jsPDF = window.jsPDF || window.jspdf?.jsPDF;
                if (!jsPDF) {
                    throw new Error('jsPDF library not available');
                }
                
                const pdf = new jsPDF('p', 'mm', 'a4');
                
                // Calculate dimensions
                const imgWidth = 210; // A4 width in mm
                const pageHeight = 295; // A4 height in mm
                const imgHeight = (canvas.height * imgWidth) / canvas.width;
                
                let heightLeft = imgHeight;
                let position = 0;

                // Add first page
                pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
                heightLeft -= pageHeight;

                // Add additional pages if content is longer than one page
                while (heightLeft >= 0) {
                    position = heightLeft - imgHeight;
                    pdf.addPage();
                    pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
                    heightLeft -= pageHeight;
                }

                // Download the PDF
                pdf.save(filename);
                
                // Hide loading state
                this.hideLoading();
                
            } catch (error) {
                console.error('PDF generation failed:', error);
                this.hideLoading();
                
                // Show error message
                if (typeof EasyInvoiceToast !== 'undefined') {
                    EasyInvoiceToast.show('error', 'Failed to generate PDF. Please try again.');
                } else if (typeof showMessage !== 'undefined') {
                    showMessage('Failed to generate PDF. Please try again.', 'error');
                } else {
                    alert('Failed to generate PDF. Please try again.');
                }
            }
        }

        showLoading() {
            // Create loading overlay
            const overlay = document.createElement('div');
            overlay.id = 'pdf-loading-overlay';
            overlay.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0, 0, 0, 0.5);
                display: flex;
                justify-content: center;
                align-items: center;
                z-index: 9999;
            `;
            
            const spinner = document.createElement('div');
            spinner.style.cssText = `
                background: white;
                padding: 20px;
                border-radius: 8px;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
                text-align: center;
            `;
            
            spinner.innerHTML = `
                <div style="margin-bottom: 10px;">
                    <svg width="40" height="40" viewBox="0 0 40 40">
                        <circle cx="20" cy="20" r="18" stroke="#e3e3e3" stroke-width="4" fill="none"/>
                        <circle cx="20" cy="20" r="18" stroke="#007cba" stroke-width="4" fill="none" 
                                stroke-dasharray="113" stroke-dashoffset="113" 
                                style="animation: spin 1s linear infinite; transform-origin: 50% 50%;">
                            <animate attributeName="stroke-dashoffset" values="113;0" dur="1s" repeatCount="indefinite"/>
                        </circle>
                    </svg>
                </div>
                <div style="color: #333; font-weight: 500;">Generating PDF...</div>
            `;
            
            overlay.appendChild(spinner);
            document.body.appendChild(overlay);
            
            // Add CSS animation
            const style = document.createElement('style');
            style.textContent = `
                @keyframes spin {
                    0% { stroke-dashoffset: 113; }
                    100% { stroke-dashoffset: 0; }
                }
            `;
            document.head.appendChild(style);
        }

        hideLoading() {
            const overlay = document.getElementById('pdf-loading-overlay');
            if (overlay) {
                overlay.remove();
            }
        }
    };

    // Backward compatibility - keep InvoicePdfGenerator for existing code
    window.InvoicePdfGenerator = window.DocumentPdfGenerator;

    // Initialize when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            // Auto-detect document type based on page content
            const isQuote = document.querySelector('.quote-content, .quote-title, .quote-number');
            const documentType = isQuote ? 'quote' : 'invoice';
            new DocumentPdfGenerator(documentType);
        });
    } else {
        // Auto-detect document type based on page content
        const isQuote = document.querySelector('.quote-content, .quote-title, .quote-number');
        const documentType = isQuote ? 'quote' : 'invoice';
        new DocumentPdfGenerator(documentType);
    }

})();

```
