Social Survey Instrument Drafter

Social Survey Instrument Drafter

Survey Title

Survey introduction text appears here.

General Settings

Survey Questions

Add a New Question

${index + 1}. ${q.text}

`; switch(q.type) { case 'text': content += ''; break; case 'textarea': content += ''; break; case 'multiple-choice': q.options.forEach(opt => { content += `
${opt}
`; }); break; case 'checkbox': q.options.forEach(opt => { content += `
${opt}
`; }); break; case 'scale': content += '
'; q.options.forEach((opt, i) => { content += `
`; }); content += '
'; break; } qDiv.innerHTML = content; els.prevQContainer.appendChild(qDiv); }); } // Reads the config UI and updates the 'questions' array function updateQuestionsFromConfig() { const newQuestions = []; const editorCards = els.qBuilderContainer.querySelectorAll('.ssi-question-editor'); editorCards.forEach(card => { const id = parseInt(card.dataset.id); const text = card.querySelector('.ssi-q-text').value; const originalQ = questions.find(q => q.id === id); const newQ = { id: id, type: originalQ.type, text: text }; if (originalQ.type === 'multiple-choice' || originalQ.type === 'checkbox' || originalQ.type === 'scale') { newQ.options = []; card.querySelectorAll('.ssi-input-option').forEach(optInp => { newQ.options.push(optInp.value); }); } newQuestions.push(newQ); }); questions = newQuestions; } function handleGenerate() { updateQuestionsFromConfig(); renderPreview(); switchTab('sheet'); // Spec II.B.4 } function handleAddQuestion() { const type = els.qTypeSelect.value; const newQ = { id: qIdCounter++, type: type, text: 'New Question: (Click to edit)' }; if (type === 'multiple-choice' || type === 'checkbox') { newQ.options = ['Option 1', 'Option 2']; } else if (type === 'scale') { newQ.options = ['1', '2', '3', '4', '5']; } questions.push(newQ); renderConfig(); // Re-render the editor list } // --- PDF DOWNLOAD (Spec II.C & VI.9) --- async function downloadPDF() { const { jsPDF } = window.jspdf; const sheet = els.sheetWrapper; // The element to capture try { const canvas = await window.html2canvas(sheet, { scale: 2, // Higher quality useCORS: true, logging: false, width: sheet.offsetWidth, }); const imgData = canvas.toDataURL('image/png'); // A4 Paper: 210mm wide, 297mm high const pdfWidth = 210; const pdfHeight = 297; const margin = 10; const doc = new jsPDF('p', 'mm', 'a4'); // Calculate aspect ratio const imgWidth = pdfWidth - (margin * 2); const imgHeight = (canvas.height * imgWidth) / canvas.width; let heightLeft = imgHeight; let position = margin; doc.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight); heightLeft -= (pdfHeight - (margin * 2)); // Handle long surveys that need multiple pages while (heightLeft > 0) { position = heightLeft - imgHeight + margin; // New position for next page doc.addPage(); doc.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight); heightLeft -= pdfHeight; } doc.save(`${els.inpTitle.value.replace(/ /g, '_') || 'survey'}.pdf`); } catch (error) { console.error("Error generating PDF:", error); alert("An error occurred while generating the PDF."); } } // --- EVENT LISTENERS (Spec IV.A) --- function attachEventListeners() { // Tabs els.tabs.forEach(btn => btn.addEventListener('click', () => switchTab(btn.dataset.tab))); els.prevTabBtn.addEventListener('click', () => switchTab('sheet')); els.nextTabBtn.addEventListener('click', () => switchTab('config')); // Main Actions els.addQBtn.addEventListener('click', handleAddQuestion); els.generateBtn.addEventListener('click', handleGenerate); els.downloadPdfBtn.addEventListener('click', downloadPDF); // Dynamic Listeners for config changes (Spec VI.4) els.qBuilderContainer.addEventListener('click', function(e) { const target = e.target; // Find the parent editor card const card = target.closest('.ssi-question-editor'); if (!card) return; const id = parseInt(card.dataset.id); const q = questions.find(q => q.id === id); // Delete Question if (target.classList.contains('ssi-delete-q-btn')) { if (confirm('Are you sure you want to delete this question?')) { questions = questions.filter(q => q.id !== id); renderConfig(); } } // Add Option if (target.classList.contains('ssi-add-option-btn')) { q.options.push('New Option'); updateQuestionsFromConfig(); // Sync array renderConfig(); // Re-render } // Remove Option if (target.classList.contains('ssi-remove-option-btn')) { const index = parseInt(target.dataset.index); q.options.splice(index, 1); updateQuestionsFromConfig(); // Sync array renderConfig(); // Re-render } }); } // --- RUN --- init(); });
Scroll to Top