The Feudal Pyramid
Glossary of Feudal Terms
${tier.details.life}
`; tierDetailsDiv.innerHTML = detailsHtml; tierDetailsDiv.style.display = 'block'; tierDetailsDiv.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } // --- Glossary Tab Logic --- function renderGlossary() { glossaryListDiv.innerHTML = ''; feudalData.glossary.sort((a,b) => a.term.localeCompare(b.term)).forEach(item => { const itemDiv = document.createElement('div'); itemDiv.classList.add('mfs-glossary-item'); itemDiv.innerHTML = `${item.term}: ${item.definition}`; glossaryListDiv.appendChild(itemDiv); }); } // --- PDF Download Logic --- downloadPdfButton.addEventListener('click', async () => { const doc = new jsPDF(); const themeAccentColor = getComputedStyle(document.documentElement).getPropertyValue('--mfs-accent-color').trim(); const pdfTextColor = '#333333'; const pdfHeaderTextColor = '#FFFFFF'; // White text on accent bg doc.setFont('MedievalSharp', 'normal'); // Set custom font if loaded and registered with jsPDF // Title doc.setFillColor(themeAccentColor); doc.rect(0, 0, doc.internal.pageSize.getWidth(), 20, 'F'); doc.setTextColor(pdfHeaderTextColor); doc.setFontSize(22); doc.text("Medieval Feudal System", doc.internal.pageSize.getWidth() / 2, 13, { align: 'center' }); let currentY = 30; // 1. Hierarchy Diagram (as image if possible, otherwise text) doc.setFontSize(16); doc.setTextColor(pdfTextColor); doc.text("The Feudal Pyramid", 14, currentY); currentY += 8; try { const canvas = await html2canvas(hierarchyDiagramDiv, { backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--mfs-primary-bg').trim(), scale: 2 // Increase scale for better resolution }); const imgData = canvas.toDataURL('image/png'); const imgProps = doc.getImageProperties(imgData); const pdfWidth = doc.internal.pageSize.getWidth() - 28; // Page width with margins const imgHeight = (imgProps.height * pdfWidth) / imgProps.width; if (currentY + imgHeight > doc.internal.pageSize.getHeight() - 20) { // Check if it fits doc.addPage(); currentY = 20; } doc.addImage(imgData, 'PNG', 14, currentY, pdfWidth, imgHeight); currentY += imgHeight + 10; } catch (e) { console.error("Error rendering hierarchy diagram to canvas:", e); doc.setFontSize(10); doc.text("Hierarchy Diagram (Visual): Please refer to the online tool.", 14, currentY); currentY += 7; // Fallback to text representation feudalData.tiers.forEach(tier => { doc.text(`${' '.repeat(tier.level * 2)}- ${tier.name}`, 14, currentY); currentY += 6; if (currentY > doc.internal.pageSize.getHeight() - 20) { doc.addPage(); currentY = 20; } }); currentY += 4; } // 2. Tier Details feudalData.tiers.forEach(tier => { if (currentY > doc.internal.pageSize.getHeight() - 60) { // Check space for header doc.addPage(); currentY = 20; } doc.setFontSize(14); doc.setFillColor(themeAccentColor); // Section header bg doc.setTextColor(pdfHeaderTextColor); doc.rect(14, currentY-4, doc.internal.pageSize.getWidth() - 28, 7, 'F'); doc.text(tier.name, 16, currentY); currentY += 10; doc.setTextColor(pdfTextColor); doc.setFontSize(10); doc.setFont('helvetica', 'bold'); doc.text("Role:", 16, currentY); currentY += 5; doc.setFont('helvetica', 'normal'); const roleLines = doc.splitTextToSize(tier.details.role, doc.internal.pageSize.getWidth() - 32); doc.text(roleLines, 16, currentY); currentY += roleLines.length * 4 + 3; if (currentY > doc.internal.pageSize.getHeight() - 20) { doc.addPage(); currentY = 20; } doc.setFont('helvetica', 'bold'); doc.text("Responsibilities:", 16, currentY); currentY += 5; doc.setFont('helvetica', 'normal'); tier.details.responsibilities.forEach(li => { const itemLines = doc.splitTextToSize(`• ${li}`, doc.internal.pageSize.getWidth() - 32); doc.text(itemLines, 16, currentY); currentY += itemLines.length * 4 + 1; if (currentY > doc.internal.pageSize.getHeight() - 20) { doc.addPage(); currentY = 20; } }); currentY += 2; doc.setFont('helvetica', 'bold'); doc.text("Rights & Privileges:", 16, currentY); currentY += 5; doc.setFont('helvetica', 'normal'); tier.details.rights.forEach(li => { const itemLines = doc.splitTextToSize(`• ${li}`, doc.internal.pageSize.getWidth() - 32); doc.text(itemLines, 16, currentY); currentY += itemLines.length * 4 + 1; if (currentY > doc.internal.pageSize.getHeight() - 20) { doc.addPage(); currentY = 20; } }); currentY += 2; doc.setFont('helvetica', 'bold'); doc.text("Daily Life Snapshot:", 16, currentY); currentY += 5; doc.setFont('helvetica', 'normal'); const lifeLines = doc.splitTextToSize(tier.details.life, doc.internal.pageSize.getWidth() - 32); doc.text(lifeLines, 16, currentY); currentY += lifeLines.length * 4 + 5; // Extra space after section if (currentY > doc.internal.pageSize.getHeight() - 20) { doc.addPage(); currentY = 20; } }); // 3. Glossary if (currentY > doc.internal.pageSize.getHeight() - 40) { doc.addPage(); currentY = 20; } doc.setFontSize(16); doc.setFont('MedievalSharp', 'normal'); doc.setTextColor(themeAccentColor); doc.text("Glossary of Terms", 14, currentY); currentY += 10; doc.setTextColor(pdfTextColor); const glossaryTableRows = feudalData.glossary.map(item => [item.term, item.definition]); doc.autoTable({ startY: currentY, head: [['Term', 'Definition']], body: glossaryTableRows, theme: 'grid', headStyles: { fillColor: themeAccentColor, textColor: pdfHeaderTextColor, fontStyle: 'bold', font: 'MedievalSharp' }, styles: { fontSize: 9, cellPadding: 2, font: 'helvetica' }, columnStyles: { 0: { fontStyle: 'bold' } }, didDrawPage: function (data) { // Add page numbers let str = "Page " + doc.internal.getNumberOfPages(); doc.setFontSize(8); doc.setTextColor(pdfTextColor); doc.text(str, data.settings.margin.left, doc.internal.pageSize.height - 10); } }); doc.save('medieval_feudal_system.pdf'); }); // Initial Render renderHierarchy(); renderGlossary(); });