PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.1.2
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.1.2
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / assets / js / document-pdf.js

document-pdf.js in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.1.2, at assets/js/document-pdf.js

215 lines 8.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Easy Invoice Document PDF Generation using html2canvas
3 * Generates PDF from the actual rendered invoice/quote HTML
4 *
5 * @package Easy_Invoice
6 * @version 1.0.0
7 */
8
9 (function() {
10 'use strict';
11
12 // Global Document PDF Generator Class
13 window.DocumentPdfGenerator = class DocumentPdfGenerator {
14 constructor(documentType = 'invoice') {
15 this.documentType = documentType; // 'invoice' or 'quote'
16 this.init();
17 }
18
19 init() {
20 // Add html2canvas script if not already loaded
21 if (typeof html2canvas === 'undefined') {
22 this.loadScript('https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js', () => {
23 this.loadScript('https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js', () => {
24 this.setupPDFButtons();
25 });
26 });
27 } else {
28 this.setupPDFButtons();
29 }
30 }
31
32 loadScript(src, callback) {
33 const script = document.createElement('script');
34 script.src = src;
35 script.onload = callback;
36 document.head.appendChild(script);
37 }
38
39 setupPDFButtons() {
40 // Find all PDF download buttons
41 const pdfButtons = document.querySelectorAll('.download-pdf-btn, .ei-download-pdf');
42
43 pdfButtons.forEach(button => {
44 button.addEventListener('click', (e) => {
45 e.preventDefault();
46 this.generatePDF();
47 });
48 });
49 }
50
51 async generatePDF() {
52 try {
53 // Show loading state
54 this.showLoading();
55
56 // Find the document content
57 const documentContent = document.querySelector('.invoice-content') ||
58 document.querySelector('.quote-content');
59
60 if (!documentContent) {
61 throw new Error('Document content not found');
62 }
63
64 // Get document data for filename
65 const documentTitle = document.querySelector('.invoice-title')?.textContent ||
66 document.querySelector('.quote-title')?.textContent ||
67 this.documentType;
68 const documentNumber = document.querySelector('.invoice-number')?.textContent ||
69 document.querySelector('.quote-number')?.textContent ||
70 '';
71 const filename = `${documentTitle}-${documentNumber}-${new Date().toISOString().split('T')[0]}.pdf`;
72
73 // Simple html2canvas configuration
74 const canvas = await html2canvas(documentContent, {
75 scale: 1.5,
76 useCORS: true,
77 allowTaint: true,
78 backgroundColor: '#ffffff',
79 logging: false
80 });
81
82 // Convert canvas to image
83 const imgData = canvas.toDataURL('image/jpeg');
84
85 // Create PDF
86 const jsPDF = window.jsPDF || window.jspdf?.jsPDF;
87 if (!jsPDF) {
88 throw new Error('jsPDF library not available');
89 }
90
91 const pdf = new jsPDF('p', 'mm', 'a4');
92
93 // Calculate dimensions
94 const imgWidth = 210; // A4 width in mm
95 const pageHeight = 295; // A4 height in mm
96 const imgHeight = (canvas.height * imgWidth) / canvas.width;
97
98 let heightLeft = imgHeight;
99 let position = 0;
100
101 // Add first page
102 pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
103 heightLeft -= pageHeight;
104
105 // Add additional pages if content is longer than one page
106 while (heightLeft >= 0) {
107 position = heightLeft - imgHeight;
108 pdf.addPage();
109 pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
110 heightLeft -= pageHeight;
111 }
112
113 // Download the PDF
114 pdf.save(filename);
115
116 // Hide loading state
117 this.hideLoading();
118
119 } catch (error) {
120 console.error('PDF generation failed:', error);
121 this.hideLoading();
122
123 // Show error message
124 if (typeof EasyInvoiceToast !== 'undefined') {
125 EasyInvoiceToast.show('error', 'Failed to generate PDF. Please try again.');
126 } else if (typeof showMessage !== 'undefined') {
127 showMessage('Failed to generate PDF. Please try again.', 'error');
128 } else {
129 alert('Failed to generate PDF. Please try again.');
130 }
131 }
132 }
133
134 showLoading() {
135 // Create loading overlay
136 const overlay = document.createElement('div');
137 overlay.id = 'pdf-loading-overlay';
138 overlay.style.cssText = `
139 position: fixed;
140 top: 0;
141 left: 0;
142 width: 100%;
143 height: 100%;
144 background: rgba(0, 0, 0, 0.5);
145 display: flex;
146 justify-content: center;
147 align-items: center;
148 z-index: 9999;
149 `;
150
151 const spinner = document.createElement('div');
152 spinner.style.cssText = `
153 background: white;
154 padding: 20px;
155 border-radius: 8px;
156 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
157 text-align: center;
158 `;
159
160 spinner.innerHTML = `
161 <div style="margin-bottom: 10px;">
162 <svg width="40" height="40" viewBox="0 0 40 40">
163 <circle cx="20" cy="20" r="18" stroke="#e3e3e3" stroke-width="4" fill="none"/>
164 <circle cx="20" cy="20" r="18" stroke="#007cba" stroke-width="4" fill="none"
165 stroke-dasharray="113" stroke-dashoffset="113"
166 style="animation: spin 1s linear infinite; transform-origin: 50% 50%;">
167 <animate attributeName="stroke-dashoffset" values="113;0" dur="1s" repeatCount="indefinite"/>
168 </circle>
169 </svg>
170 </div>
171 <div style="color: #333; font-weight: 500;">Generating PDF...</div>
172 `;
173
174 overlay.appendChild(spinner);
175 document.body.appendChild(overlay);
176
177 // Add CSS animation
178 const style = document.createElement('style');
179 style.textContent = `
180 @keyframes spin {
181 0% { stroke-dashoffset: 113; }
182 100% { stroke-dashoffset: 0; }
183 }
184 `;
185 document.head.appendChild(style);
186 }
187
188 hideLoading() {
189 const overlay = document.getElementById('pdf-loading-overlay');
190 if (overlay) {
191 overlay.remove();
192 }
193 }
194 };
195
196 // Backward compatibility - keep InvoicePdfGenerator for existing code
197 window.InvoicePdfGenerator = window.DocumentPdfGenerator;
198
199 // Initialize when DOM is ready
200 if (document.readyState === 'loading') {
201 document.addEventListener('DOMContentLoaded', () => {
202 // Auto-detect document type based on page content
203 const isQuote = document.querySelector('.quote-content, .quote-title, .quote-number');
204 const documentType = isQuote ? 'quote' : 'invoice';
205 new DocumentPdfGenerator(documentType);
206 });
207 } else {
208 // Auto-detect document type based on page content
209 const isQuote = document.querySelector('.quote-content, .quote-title, .quote-number');
210 const documentType = isQuote ? 'quote' : 'invoice';
211 new DocumentPdfGenerator(documentType);
212 }
213
214 })();
215