Funeral Eulogy Generator
A guided tool to help you craft a heartfelt tribute.
This is the generated eulogy based on your inputs. Please review it below. You can go back to previous tabs to make edits.
They had such a deep passion for ${passion.replace(/\n/g, '
')}
The impact ${name} had on the people around them is immeasurable. ${impact.replace(/\n/g, '
')}
${closing.replace(/\n/g, '
')}
Thank you. ${name}, you will be deeply missed, but never forgotten.
`; } eulogyOutputDiv.innerHTML = eulogyText; currentTab = tabs.length - 1; showTab(currentTab); } /** * [REVISED] Generates and downloads a well-formatted, text-based PDF of the eulogy. * This version uses jsPDF's native text functions for a clean layout and small file size. */ function downloadPDF() { const name = document.getElementById('deceasedName').value.trim() || "[Deceased's Name]"; const relationship = document.getElementById('yourRelationship').value.trim(); const opening = document.getElementById('openingStatement').value.trim(); const firstMemory = document.getElementById('firstMemory').value.trim(); const funnyStory = document.getElementById('funnyStory').value.trim(); const qualities = document.getElementById('keyQualities').value.trim(); const passion = document.getElementById('passion').value.trim(); const impact = document.getElementById('impact').value.trim(); const closing = document.getElementById('closingMessage').value.trim(); const filename = `Eulogy for ${name}.pdf`; const { jsPDF } = window.jspdf; const doc = new jsPDF({ unit: 'pt', format: 'a4' }); const pageHeight = doc.internal.pageSize.height; const pageWidth = doc.internal.pageSize.width; const margin = 50; const contentWidth = pageWidth - margin * 2; let cursorY = margin; let pageNumber = 1; // Helper function to add text and manage page breaks const addText = (text, options) => { const { size = 11, style = 'normal', spaceAfter = 12, isHeading = false, align = 'left' } = options; doc.setFont('times', style); doc.setFontSize(size); const lines = doc.splitTextToSize(text, contentWidth); // Check if there's enough space for the whole block, otherwise start a new page const blockHeight = lines.length * (size * 1.15) + spaceAfter; if (cursorY + blockHeight > pageHeight - margin) { addFooter(); doc.addPage(); pageNumber++; cursorY = margin; addHeader(); } // For headings, add a bit more space before if(isHeading) { cursorY += 8; } // Determine the correct X position based on text alignment let xPos = margin; // Default for left alignment if (align === 'center') { xPos = pageWidth / 2; } else if (align === 'right') { xPos = pageWidth - margin; } doc.text(lines, xPos, cursorY, { align: align }); cursorY += lines.length * (size * 1.15) + spaceAfter; }; const addHeader = () => { doc.setFont('times', 'italic'); doc.setFontSize(9); doc.setTextColor(150); doc.text(`A Tribute to ${name}`, margin, margin / 2); doc.setTextColor(0); }; const addFooter = () => { doc.setFont('times', 'italic'); doc.setFontSize(9); doc.setTextColor(150); doc.text(`Page ${pageNumber}`, pageWidth - margin, pageHeight - margin / 2, {align: 'right'}); doc.setTextColor(0); } // --- Start Building PDF --- addHeader(); // Main Title addText('In Loving Memory of', { size: 24, style: 'bold', align: 'center', spaceAfter: 15 }); addText(name, { size: 20, style: 'italic', align: 'center', spaceAfter: 40 }); // Decorative Line doc.setDrawColor(180, 180, 180); doc.line(margin, cursorY, pageWidth - margin, cursorY); cursorY += 30; // Content Sections const introText = opening || `We are gathered here today to celebrate the life of ${name}. ${relationship ? `As ${name}'s ${relationship}, I` : 'I'} wanted to share a few words about what a remarkable person they were.`; addText('Introduction', { size: 14, style: 'bold', isHeading: true }); addText(introText, {}); if (firstMemory || funnyStory) { addText('Cherished Memories', { size: 14, style: 'bold', isHeading: true }); if (firstMemory) addText(firstMemory, {}); if (funnyStory) addText(funnyStory, {}); } if (qualities || passion) { addText('Their Unique Spirit', { size: 14, style: 'bold', isHeading: true }); if (qualities) addText(`Some of the words that best describe them are: ${qualities}.`, {}); if (passion) addText(passion, {}); } if (impact) { addText('A Lasting Legacy', { size: 14, style: 'bold', isHeading: true }); addText(impact, {}); } const closingText = closing || `Thank you. ${name}, you will be deeply missed, but never forgotten.`; addText('A Final Farewell', { size: 14, style: 'bold', isHeading: true }); addText(closingText, {}); addFooter(); doc.save(filename); } // --- Event Handling --- nextButton.addEventListener('click', () => { if (currentTab < tabs.length - 2) { currentTab++; showTab(currentTab); } }); prevButton.addEventListener('click', () => { if (currentTab > 0) { currentTab--; showTab(currentTab); } }); generateButton.addEventListener('click', generateEulogy); downloadPdfButton.addEventListener('click', downloadPDF); tabs.forEach(tab => { tab.addEventListener('click', () => { const tabIndex = parseInt(tab.dataset.tab, 10); if (tabIndex === tabs.length - 1 && eulogyOutputDiv.innerHTML.trim() === '') { generateEulogy(); } else { currentTab = tabIndex; showTab(currentTab); } }); }); // --- Initialization --- showTab(0); });