I affirm that the work I am submitting is entirely my own.
Signature: ${escapeHTML(pledgeData.studentName)}
Date: ${escapeHTML(pledgeData.date)}
`;
};
// --- PDF Generation (Adhering to Spec II.C) ---
// This function builds a PDF from scratch, ensuring no UI elements are included.
const generatePDF = () => {
// Ensure library is loaded
if (typeof jspdf === 'undefined') {
alert('PDF library is still loading. Please try again in a moment.');
return;
}
// Update state one last time
generatePledgePreview();
const { jsPDF } = jspdf;
const pdf = new jsPDF('p', 'pt', 'a4');
const pdfWidth = pdf.internal.pageSize.getWidth();
const margin = 40;
const contentWidth = pdfWidth - (margin * 2);
let yPos = margin;
// Title
pdf.setFont('helvetica', 'bold');
pdf.setFontSize(18);
pdf.text('Academic Honesty Pledge', pdfWidth / 2, yPos, { align: 'center' });
yPos += 30;
// Course Details
pdf.setFont('helvetica', 'normal');
pdf.setFontSize(12);
pdf.text(`Course: ${pledgeData.course}`, margin, yPos);
yPos += 20;
pdf.text(`Instructor: ${pledgeData.instructor}`, margin, yPos);
yPos += 20;
pdf.text(`Assignment: ${pledgeData.assignment}`, margin, yPos);
yPos += 25;
// Line separator
pdf.setDrawColor(180);
pdf.line(margin, yPos, pdfWidth - margin, yPos);
yPos += 30;
// Pledge Body
const studentName = pledgeData.studentName || '[Student Name]';
const pledgeText = `On my honor, I, ${studentName}, pledge that I have abided by the following rules for this assignment:`;
const splitText = pdf.splitTextToSize(pledgeText, contentWidth);
pdf.text(splitText, margin, yPos);
yPos += (splitText.length * 15) + 10;
// Rules
pdf.setFont('courier', 'normal');
pledgeData.rules.forEach(rule => {
const ruleText = pdf.splitTextToSize(`- ${rule}`, contentWidth - 20); // Indent
pdf.text(ruleText, margin + 20, yPos);
yPos += (ruleText.length * 15) + 5;
});
yPos += 15;
// Affirmation
pdf.setFont('helvetica', 'normal');
const affirmationText = 'I affirm that the work I am submitting is entirely my own.';
const splitAffirmation = pdf.splitTextToSize(affirmationText, contentWidth);
pdf.text(splitAffirmation, margin, yPos);
yPos += (splitAffirmation.length * 15) + 40; // Extra space
// Signature & Date
pdf.setFont('helvetica', 'bold');
pdf.text(`Signature: ${studentName}`, margin, yPos);
yPos += 25;
pdf.text(`Date: ${pledgeData.date}`, margin, yPos);
// Save
pdf.save('Academic_Pledge.pdf');
};
// --- Utility ---
const escapeHTML = (str) => {
return str.replace(/[&<>"']/g, function(match) {
return {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}[match];
});
};
// --- Event Listeners (Adhering to Spec IV.A & IV.C) ---
// Tab switching
tabButtons.forEach(button => {
button.addEventListener('click', () => {
switchTab(button.dataset.tabId);
});
});
// Bottom nav buttons
if (nextTabBtn) {
nextTabBtn.addEventListener('click', () => navigateTabs('next'));
}
if (prevTabBtn) {
prevTabBtn.addEventListener('click', () => navigateTabs('prev'));
}
// PDF download
if (downloadPdfBtn) {
downloadPdfBtn.addEventListener('click', generatePDF);
}
// Auto-update preview on any input change
const allInputs = [
inputInstructor, inputCourse, inputAssignment,
inputCustomRules, inputStudentName, inputDate
];
allInputs.forEach(input => {
if (input) {
input.addEventListener('input', generatePledgePreview);
}
});
rulesCheckboxes.forEach(box => {
box.addEventListener('change', generatePledgePreview);
});
// --- Initial Load ---
const init = () => {
// Set default date
if (inputDate) {
inputDate.value = new Date().toISOString().split('T')[0];
}
// Set first tab as active and generate initial preview
switchTab('pledgeTabConfig');
generatePledgePreview();
};
init(); // Run the tool
});