Interactive Venn Diagram Creator
Diagram (Counts)
Element Breakdown
Please enter elements into the sets to generate a diagram.
"; } else { // Handle cases like fully disjoint sets if venn.js didn't draw anything diagramDiv.innerHTML = "Diagram could not be drawn (sets might be disjoint or empty). See element breakdown below.
"; } // --- 5. Display Textual Results --- let resultsHTML = ''; const addResultLine = (label, setData) => { const elements = [...setData]; resultsHTML += `${label}: (${elements.length}) ${elements.length > 0 ? elements.join(', ') : '(empty)'}
`;
};
if (numSets === 2) {
addResultLine(`Elements only in ${nameA}`, results.A_only);
addResultLine(`Elements only in ${nameB}`, results.B_only);
addResultLine(`Elements in ${nameA} and ${nameB}`, results.A_B);
} else {
addResultLine(`Elements only in ${nameA}`, results.A_only);
addResultLine(`Elements only in ${nameB}`, results.B_only);
addResultLine(`Elements only in ${nameC}`, results.C_only);
addResultLine(`Elements in ${nameA} and ${nameB} (but not ${nameC})`, results.A_B_only);
addResultLine(`Elements in ${nameA} and ${nameC} (but not ${nameB})`, results.A_C_only);
addResultLine(`Elements in ${nameB} and ${nameC} (but not ${nameA})`, results.B_C_only);
addResultLine(`Elements in ${nameA}, ${nameB}, and ${nameC}`, results.A_B_C);
}
listResultsContainer.innerHTML = resultsHTML;
resultsListDiv.style.display = 'block';
// --- 6. Enable PDF Download ---
currentResults = results; // Save for PDF
downloadBtn.style.display = 'block';
} catch (error) {
console.error("Error generating Venn Diagram:", error);
displayError("An error occurred: " + error.message);
}
});
// --- PDF Generation ---
downloadBtn.addEventListener('click', () => {
if (!currentResults || typeof jspdf === 'undefined') {
alert("Please generate a diagram first, or jsPDF library is not loaded.");
return;
}
try {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const computedStyle = getComputedStyle(creatorDiv);
const primaryColor = computedStyle.getPropertyValue('--vdc-primary-color').trim();
const textColor = computedStyle.getPropertyValue('--vdc-text-color').trim();
const secondaryColor = computedStyle.getPropertyValue('--vdc-secondary-color').trim();
let yPos = 20;
const lineSpacing = 7; // Smaller spacing for lists
const sectionSpacing = 12;
const indent = 15;
const pageWidth = doc.internal.pageSize.getWidth();
const wrapWidth = pageWidth - indent * 2;
// Title
doc.setFontSize(18);
doc.setTextColor(primaryColor);
doc.text("Venn Diagram Analysis Results", pageWidth / 2, yPos, { align: 'center' });
yPos += sectionSpacing;
// Input Sets
doc.setFontSize(14);
doc.setTextColor(textColor);
doc.text("Input Sets:", indent, yPos);
yPos += lineSpacing * 1.5;
doc.setFontSize(11);
doc.setFont(undefined, 'bold');
doc.text(`${currentResults.nameA}:`, indent, yPos);
doc.setFont(undefined, 'normal');
let elementsText = currentResults.rawSetA.length > 0 ? currentResults.rawSetA.join(', ') : '(empty)';
let lines = doc.splitTextToSize(elementsText, wrapWidth - 30); // Adjust width for label
doc.text(lines, indent + 30, yPos);
yPos += lines.length * lineSpacing;
doc.setFont(undefined, 'bold');
doc.text(`${currentResults.nameB}:`, indent, yPos);
doc.setFont(undefined, 'normal');
elementsText = currentResults.rawSetB.length > 0 ? currentResults.rawSetB.join(', ') : '(empty)';
lines = doc.splitTextToSize(elementsText, wrapWidth - 30);
doc.text(lines, indent + 30, yPos);
yPos += lines.length * lineSpacing;
if (numSets === 3 && currentResults.nameC) {
doc.setFont(undefined, 'bold');
doc.text(`${currentResults.nameC}:`, indent, yPos);
doc.setFont(undefined, 'normal');
elementsText = currentResults.rawSetC.length > 0 ? currentResults.rawSetC.join(', ') : '(empty)';
lines = doc.splitTextToSize(elementsText, wrapWidth - 30);
doc.text(lines, indent + 30, yPos);
yPos += lines.length * lineSpacing;
}
yPos += sectionSpacing / 2; // Space before breakdown
// Element Breakdown Section
doc.setFontSize(14);
doc.setTextColor(textColor);
doc.text("Element Breakdown:", indent, yPos);
yPos += lineSpacing * 1.5;
doc.setFontSize(10); // Smaller font for the list
const addPdfLine = (label, setData) => {
if (yPos > doc.internal.pageSize.getHeight() - 20) { // Add new page if needed
doc.addPage();
yPos = 20;
}
const elements = [...setData];
const count = elements.length;
doc.setFont(undefined, 'bold');
doc.text(`${label}: (${count})`, indent, yPos);
yPos += lineSpacing;
doc.setFont(undefined, 'normal');
if (count > 0) {
let elementListStr = elements.join(', ');
let elementLines = doc.splitTextToSize(elementListStr, wrapWidth - 5); // Indent slightly
doc.setTextColor(secondaryColor); // Use secondary color for elements
doc.text(elementLines, indent + 5, yPos);
doc.setTextColor(textColor); // Reset text color
yPos += elementLines.length * (lineSpacing - 1); // Slightly tighter spacing for list items
} else {
doc.setTextColor(secondaryColor);
doc.text('(empty)', indent + 5, yPos);
doc.setTextColor(textColor);
yPos += lineSpacing - 1;
}
yPos += 3; // Small gap between items
};
// Generate lines based on numSets
if (numSets === 2) {
addPdfLine(`Only in ${currentResults.nameA}`, currentResults.A_only);
addPdfLine(`Only in ${currentResults.nameB}`, currentResults.B_only);
addPdfLine(`In ${currentResults.nameA} and ${currentResults.nameB}`, currentResults.A_B);
} else {
addPdfLine(`Only in ${currentResults.nameA}`, currentResults.A_only);
addPdfLine(`Only in ${currentResults.nameB}`, currentResults.B_only);
addPdfLine(`Only in ${currentResults.nameC}`, currentResults.C_only);
addPdfLine(`In ${currentResults.nameA} & ${currentResults.nameB} (not ${currentResults.nameC})`, currentResults.A_B_only);
addPdfLine(`In ${currentResults.nameA} & ${currentResults.nameC} (not ${currentResults.nameB})`, currentResults.A_C_only);
addPdfLine(`In ${currentResults.nameB} & ${currentResults.nameC} (not ${currentResults.nameA})`, currentResults.B_C_only);
addPdfLine(`In ${currentResults.nameA} & ${currentResults.nameB} & ${currentResults.nameC}`, currentResults.A_B_C);
}
// Footer (Optional)
const pageCount = doc.internal.getNumberOfPages();
for (let i = 1; i <= pageCount; i++) {
doc.setPage(i);
const footerY = doc.internal.pageSize.getHeight() - 10;
doc.setFontSize(9);
doc.setTextColor(secondaryColor);
doc.text(`Page ${i} of ${pageCount}`, pageWidth / 2, footerY, { align: 'center' });
doc.text(`Generated: ${new Date().toLocaleString()}`, indent, footerY);
}
// Save PDF
doc.save('venn-diagram-analysis.pdf');
} catch (error) {
console.error("Error generating PDF:", error);
alert("An error occurred while generating the PDF. Check console.");
}
});
})(); // End IIFE
