Speech Generator

Speech Generator

Craft, structure, and refine your next compelling speech.

Draft Your Speech

Speech Templates

Click a template to load it into the composer.

Speech Analysis

Write your speech in the composer to generate an analysis of its tone and pacing.

${template.body.substring(0, 90)}...

`).join(''); } templateListEl.addEventListener('click', e => { const templateCard = e.target.closest('div[data-body]'); if (templateCard) { bodyInput.value = decodeURIComponent(templateCard.dataset.body); speechData.body = bodyInput.value; runAnalysis(); switchTab(0); } }); // --- TAB LOGIC --- let currentTabIndex = 0; const tabs = ['composer', 'templates', 'analysis']; function switchTab(tabIndex) { currentTabIndex = tabIndex; tabBtns.forEach((btn, index) => { const tabName = btn.dataset.tab; document.getElementById(`${tabName}-content`).classList.toggle('active', index === tabIndex); btn.classList.toggle('active', index === tabIndex); }); prevTabBtn.disabled = tabIndex === 0; nextTabBtn.disabled = tabIndex === tabs.length - 1; } tabBtns.forEach((button, index) => button.addEventListener('click', () => switchTab(index))); prevTabBtn.addEventListener('click', () => { if (currentTabIndex > 0) switchTab(currentTabIndex - 1); }); nextTabBtn.addEventListener('click', () => { if (currentTabIndex < tabs.length - 1) switchTab(currentTabIndex + 1); }); // --- PDF GENERATION --- async function generatePdfReport() { const button = downloadPdfBtn; const originalText = button.textContent; button.disabled = true; button.textContent = 'Generating...'; const reportHtml = `

${speechData.title || 'Speech Script'}

${speechData.event || 'Event'}

${speechData.body || 'No content provided.'}

SPEAKER

${speechData.speaker || 'N/A'}

METRICS

Time:
${speechData.analysis.time}
Tone:
${speechData.analysis.tone.charAt(0).toUpperCase() + speechData.analysis.tone.slice(1)}
Words:
${speechData.analysis.words}

DELIVERY CUES

    ${speechData.analysis.cues.map(cue => `
  • ${cue}
  • `).join('')}
`; const pdfTemplate = document.getElementById('pdf-template'); pdfTemplate.innerHTML = reportHtml; pdfTemplate.classList.remove('invisible'); try { const { jsPDF } = window.jspdf; const canvas = await html2canvas(pdfTemplate.querySelector('.pdf-report-container'), { scale: 3, useCORS: true }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = (canvas.height * pdfWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight); pdf.save(`${(speechData.title || 'Speech_Script').replace(/\s+/g, '_')}.pdf`); } catch(e) { console.error('PDF Generation Error:', e); alert('Failed to generate PDF. See console for details.'); } finally { button.disabled = false; button.textContent = originalText; pdfTemplate.innerHTML = ''; pdfTemplate.classList.add('invisible'); } } downloadPdfBtn.addEventListener('click', generatePdfReport); // --- INITIALIZATION --- switchTab(0); renderTemplates(); runAnalysis(); });
Scroll to Top