Public Speaking Script Generator
Structure your speech from hook to conclusion with this guided tool.
Your generated script will appear here for preview.
Remember, if you take away just one thing today, it's this: ${getValue('keyTakeaway')}
`; if(getValue('callToAction')) html += `[Call to action]
${getValue('callToAction').replace(/\n/g, '
')}
[Deliver closing statement]
${getValue('closingStatement')}
`; scriptPreviewOutput.innerHTML = html || 'No content to display. Please fill out the fields in the previous tabs.
'; downloadPdfBtn.classList.remove('hidden'); }; const downloadPDF = () => { const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const PAGE_WIDTH = pdf.internal.pageSize.getWidth(); const MARGIN = 50; const MAX_WIDTH = PAGE_WIDTH - MARGIN * 2; let y = MARGIN; const checkPageBreak = (spaceNeeded) => { if (y + spaceNeeded > pdf.internal.pageSize.getHeight() - MARGIN) { pdf.addPage(); y = MARGIN; } }; const addTitle = (text) => { checkPageBreak(60); pdf.setFontSize(24); pdf.setFont("times", "bold"); pdf.setTextColor(0, 0, 0); pdf.text(text, PAGE_WIDTH / 2, y, { align: 'center' }); y += 20; const speakerName = getValue('speakerName'); if (speakerName) { pdf.setFontSize(14); pdf.setFont("times", "normal"); pdf.setTextColor(100, 100, 100); pdf.text(`by ${speakerName}`, PAGE_WIDTH / 2, y, { align: 'center' }); y += 40; } }; const addSectionHeader = (text) => { checkPageBreak(40); pdf.setFontSize(16); pdf.setFont("times", "bold"); pdf.setTextColor(0, 0, 0); pdf.text(text.toUpperCase(), MARGIN, y); y += 25; }; const addCue = (text) => { checkPageBreak(20); pdf.setFontSize(12); pdf.setFont("times", "italic"); pdf.setTextColor(150, 150, 150); const lines = pdf.splitTextToSize(text, MAX_WIDTH); pdf.text(lines, MARGIN + 20, y); y += lines.length * 14 + 5; }; const addParagraph = (text) => { checkPageBreak(20); pdf.setFontSize(12); pdf.setFont("times", "normal"); pdf.setTextColor(50, 50, 50); const lines = pdf.splitTextToSize(text, MAX_WIDTH); pdf.text(lines, MARGIN, y); y += lines.length * 14 + 15; }; // --- PDF Content Generation --- addTitle(getValue('speechTitle') || "My Speech"); addSectionHeader("Introduction"); if (getValue('openingHook')) { addCue("[OPENING HOOK]"); addParagraph(getValue('openingHook')); } if (getValue('credibility')) { addCue("[CREDIBILITY]"); addParagraph(getValue('credibility')); } if (getValue('agenda')) { addCue("[AGENDA]"); addParagraph(getValue('agenda')); } addSectionHeader("Main Body"); const pointBlocks = pointsContainer.querySelectorAll('[id^="point-block-"]'); pointBlocks.forEach((block, index) => { const title = block.querySelector('.point-title').value.trim(); const details = block.querySelector('.point-details').value.trim(); if (title && details) { addCue(`[MAIN POINT ${index + 1}: ${title.toUpperCase()}]`); addParagraph(details); } }); addSectionHeader("Conclusion"); if (getValue('summary')) { addCue("[SUMMARY]"); addParagraph(getValue('summary')); } if (getValue('keyTakeaway')) { addCue("[KEY TAKEAWAY]"); addParagraph(`Remember this: ${getValue('keyTakeaway')}`); } if (getValue('callToAction')) { addCue("[CALL TO ACTION]"); addParagraph(getValue('callToAction')); } if (getValue('closingStatement')) { addCue("[CLOSING STATEMENT]"); addParagraph(getValue('closingStatement')); } pdf.save(`${(getValue('speechTitle') || 'Speech').replace(/ /g, '_')}.pdf`); }; // --- EVENT LISTENERS --- tabButtons.forEach((button, index) => button.addEventListener('click', () => showTab(index))); prevBtn.addEventListener('click', () => { if (currentTab > 0) showTab(currentTab - 1); }); nextBtn.addEventListener('click', () => { if (currentTab < tabButtons.length - 1) showTab(currentTab + 1); }); addPointBtn.addEventListener('click', addMainPoint); generateScriptBtn.addEventListener('click', generateScriptPreview); downloadPdfBtn.addEventListener('click', downloadPDF); // --- INITIALIZATION --- addMainPoint(); // Start with one main point block updateTabs(); });