No criteria added yet. Click "Add New Criterion" to start.
';
}
criteria.forEach(c => {
const div = document.createElement('div');
div.className = 'pbl-criterion-card';
div.innerHTML = `
`;
criteriaListContainer.appendChild(div);
});
// Add event listeners for new elements
criteriaListContainer.querySelectorAll('button[data-remove-id]').forEach(btn => {
btn.addEventListener('click', (e) => {
removeCriterion(parseInt(e.target.dataset.removeId));
});
});
criteriaListContainer.querySelectorAll('input[data-id], textarea[data-id]').forEach(input => {
input.addEventListener('change', (e) => { // 'change' is less resource-intensive than 'keyup'
updateCriterion(parseInt(e.target.dataset.id), e.target.dataset.field, e.target.value);
});
});
};
// --- Summary & Download Functions ---
const generatePreview = () => {
const projectTitle = escapeHTML(projectTitleInput.value || "Project Title");
const rubricTitle = escapeHTML(rubricTitleInput.value || "Rubric");
let tableHTML = `
${projectTitle}: ${rubricTitle}
`;
tableHTML += `
| Criterion |
Exemplary (4) |
Proficient (3) |
Developing (2) |
Beginning (1) |
`;
if (criteria.length === 0) {
tableHTML += '| No criteria defined in Tab 2. |
';
} else {
criteria.forEach(c => {
tableHTML += `
| ${escapeHTML(c.title)} |
${escapeHTML(c.desc_ex)} |
${escapeHTML(c.desc_pro)} |
${escapeHTML(c.desc_dev)} |
${escapeHTML(c.desc_beg)} |
`;
});
}
tableHTML += `
`;
summaryPreview.innerHTML = tableHTML;
};
const downloadPDF = () => {
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') {
alert('Error: jsPDF library not loaded.');
return;
}
if (typeof window.jspdf.autoTable === 'undefined') {
alert('Error: jsPDF-AutoTable library not loaded.');
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF('l', 'mm', 'a4'); // 'l' for landscape
const projectTitle = projectTitleInput.value || "Project Title";
const rubricTitle = rubricTitleInput.value || "Rubric";
const author = authorInput.value || "";
const margin = 15;
const pageWidth = doc.internal.pageSize.getWidth();
doc.setFontSize(18);
doc.setFont(undefined, 'bold');
doc.setTextColor(44, 62, 80);
doc.text(`${projectTitle}: ${rubricTitle}`, pageWidth / 2, margin, { align: 'center' });
if (author) {
doc.setFontSize(11);
doc.setFont(undefined, 'normal');
doc.setTextColor(108, 117, 125);
doc.text(author, pageWidth / 2, margin + 7, { align: 'center' });
}
const head = [['Criterion', 'Exemplary (4)', 'Proficient (3)', 'Developing (2)', 'Beginning (1)A']];
const body = criteria.map(c => [
c.title,
c.desc_ex,
c.desc_pro,
c.desc_dev,
c.desc_beg
]);
doc.autoTable({
head: head,
body: body,
startY: margin + 15,
theme: 'grid',
headStyles: {
fillColor: [0, 123, 255],
textColor: [255, 255, 255],
fontSize: 10,
fontStyle: 'bold'
},
styles: {
fontSize: 9,
cellPadding: 2,
valign: 'top'
},
columnStyles: {
0: { fontStyle: 'bold', minCellWidth: 40 }, // Criterion
1: { minCellWidth: 50 }, // Exemplary
2: { minCellWidth: 50 }, // Proficient
3: { minCellWidth: 50 }, // Developing
4: { minCellWidth: 50 } // Beginning
}
});
doc.save(`rubric_${projectTitle.replace(/ /g, '_') || 'pbl'}.pdf`);
};
// --- Event Listeners ---
// Tab Buttons
tabButtons.forEach((btn, index) => {
btn.addEventListener('click', () => showTab(index + 1));
});
// Next/Prev Navigation
nextBtn.addEventListener('click', () => showTab(currentTab + 1));
prevBtn.addEventListener('click', () => showTab(currentTab - 1));
// Tab 2 Actions
addCriterionBtn.addEventListener('click', () => addCriterion());
// Tab 3 Actions
downloadPdfBtn.addEventListener('click', downloadPDF);
// --- Initialization ---
// Pre-populate with sample data
addCriterion({
title: "Research & Inquiry",
desc_ex: "Goes far beyond the prompt, finding unique sources and synthesizing them in a novel way. Asks deep, insightful questions.",
desc_pro: "Gathers all required information from provided and self-found sources. Answers all guiding questions.",
desc_dev: "Gathers most of the required information, but relies heavily on provided sources. Answers are basic.",
desc_beg: "Fails to gather required information. Sources are missing or not relevant."
});
addCriterion({
title: "Collaboration & Teamwork",
desc_ex: "Actively helps teammates, mediates conflict, and ensures everyone contributes. Elevates the entire group's performance.",
desc_pro: "Completes all assigned tasks reliably. Communicates clearly with the team and listens to others' ideas.",
desc_dev: "Participates, but communication is inconsistent. Sometimes fails to complete tasks on time.",
desc_beg: "Does not participate, is disruptive, or prevents others from working."
});
renderCriteria(); // Initial render of sample data
showTab(1); // Set initial state
});