Online Story Plot Generator
Select your core story elements to generate a unique plot outline.
Act 3: ${conflictData.climax}
`; lastResult = { inputs: { genre, protagonist: protagonistSelect.options[protagonistSelect.selectedIndex].text, setting: settingSelect.options[settingSelect.selectedIndex].text, conflict: conflictSelect.options[conflictSelect.selectedIndex].text }, plot, plotText: `In a ${genre} story, ${protagonistText} ${settingText}\n\nAct 1: ${conflictData.opening} that challenges everything they know.\n\nAct 2: ${conflictData.midpoint}\n\nAct 3: ${conflictData.climax}` }; displayPlot(plot); } catch (error) { errorMessage.textContent = "Could not generate plot. Please try again."; console.error(error); resultsSection.classList.add('hidden'); } }; /** * Renders the plot in the UI. * @param {string} plotHtml - The HTML string of the generated plot. */ const displayPlot = (plotHtml) => { plotOutputDiv.innerHTML = plotHtml; resultsSection.classList.remove('hidden'); }; /** * Generates and triggers the download of a PDF report. */ const generatePdf = () => { if (!lastResult) { alert("Please generate a plot first."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFontSize(20); doc.text("Story Plot Generator Report", 105, 20, { align: 'center' }); // Input Selections Table doc.autoTable({ startY: 30, head: [['Story Element', 'Selection']], body: Object.entries(lastResult.inputs), theme: 'grid', headStyles: { fillColor: [109, 40, 217] }, // violet-700 }); // Generated Plot doc.setFontSize(14); doc.text("Generated Plot Outline", 14, doc.lastAutoTable.finalY + 15); const plotLines = doc.splitTextToSize(lastResult.plotText, 180); doc.setFontSize(11); doc.text(plotLines, 14, doc.lastAutoTable.finalY + 22); doc.save('Story_Plot_Outline.pdf'); }; // --- EVENT LISTENERS --- generateBtn.addEventListener('click', handleGeneration); downloadPdfBtn.addEventListener('click', generatePdf); });