World War Timeline Creator

Manage World War Events

Add New Event

Current Events Logged (0)

No events added yet.

Customize Timeline & Export

My World War Timeline

Conflict: ${event.warConflict}

`; if (event.theater) metaHtml += `

Theater/Front: ${event.theater}

`; if (event.category) metaHtml += `

Category: ${event.category}

`; card.innerHTML = `
${event.displayDate}
${event.title}
${metaHtml}

${event.description.replace(/\n/g, '
')}

`; timelinePreviewDiv.appendChild(card); }); } function handlePdfDownload() { if (!jsPDF_constructor_for_tool) { alert("PDF library is not available."); return; } const eventsToExport = getSortedEvents(); const pdfTimelineTitle = timelineTitleInput.value; if (eventsToExport.length === 0) { alert("No events to export."); return; } const pdf = new jsPDF_constructor_for_tool({ orientation: 'p', unit: 'mm', format: 'a4' }); const primaryColor = primaryColorInput.value; const textColor = textColorInput.value; const pageBgColor = bgColorInput.value; pdf.setFillColor(pageBgColor); pdf.rect(0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight(), 'F'); const margin = 15; const contentWidth = pdf.internal.pageSize.getWidth() - 2 * margin; let currentY = margin; pdf.setFontSize(18); pdf.setTextColor(primaryColor); const titleLines = pdf.splitTextToSize(pdfTimelineTitle, contentWidth); pdf.text(titleLines, pdf.internal.pageSize.getWidth() / 2, currentY, { align: 'center' }); currentY += (titleLines.length * 18 * 0.35) + 10; let pageFirstEventY = currentY; eventsToExport.forEach(event => { let estimatedBlockHeight = 0; pdf.setFontSize(10); estimatedBlockHeight += 5; // Display Date pdf.setFontSize(12); estimatedBlockHeight += (pdf.splitTextToSize(event.title, contentWidth).length * 12 * 0.35) + 3; // Title pdf.setFontSize(9); // Meta estimatedBlockHeight += 4; // War/Conflict if (event.theater) estimatedBlockHeight += 4; if (event.category) estimatedBlockHeight += 4; pdf.setFontSize(10); // Description if (event.description) estimatedBlockHeight += (pdf.splitTextToSize(event.description, contentWidth).length * 10 * 0.35); estimatedBlockHeight += 10; // Spacing if (currentY + estimatedBlockHeight > pdf.internal.pageSize.getHeight() - margin) { pdf.setDrawColor(primaryColor); pdf.setLineWidth(0.6); if (currentY > pageFirstEventY) pdf.line(margin + 2, pageFirstEventY - 2, margin + 2, currentY - 5); // Timeline bar for current page pdf.addPage(); currentY = margin; pageFirstEventY = currentY; pdf.setFillColor(pageBgColor); pdf.rect(0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight(), 'F'); } const eventDotY = currentY + 2; // Align dot with Display Date pdf.setFontSize(10); pdf.setTextColor(textColor); pdf.text(event.displayDate, margin + 7, currentY); currentY += 5; pdf.setFontSize(12); pdf.setTextColor(primaryColor); const eventTitleLines = pdf.splitTextToSize(event.title, contentWidth - 7); // Indent for timeline pdf.text(eventTitleLines, margin + 7, currentY); currentY += (eventTitleLines.length * 12 * 0.35) + 3; pdf.setFontSize(9); pdf.setTextColor(textColor); let metaText = `Conflict: ${event.warConflict}`; if (event.theater) metaText += ` | Theater: ${event.theater}`; if (event.category) metaText += ` | Category: ${event.category}`; const metaLines = pdf.splitTextToSize(metaText, contentWidth - 7); pdf.text(metaLines, margin + 7, currentY); currentY += (metaLines.length * 9 * 0.35) + 3; if (event.description) { pdf.setFontSize(10); const descLines = pdf.splitTextToSize(event.description, contentWidth - 7); pdf.text(descLines, margin + 7, currentY); currentY += (descLines.length * 10 * 0.35); } currentY += 7; // Space after event // Event Dot pdf.setFillColor(primaryColor); pdf.setDrawColor(primaryColor); pdf.circle(margin + 2, eventDotY, 1.5, 'FD'); }); // Final timeline bar segment pdf.setDrawColor(primaryColor); pdf.setLineWidth(0.6); if (eventsToExport.length > 0 && currentY > pageFirstEventY) { // Check if currentY moved pdf.line(margin + 2, pageFirstEventY -2 , margin + 2, currentY - 7); } let safePdfTitle = pdfTimelineTitle.replace(/[^a-z0-9]/gi, '_').toLowerCase() || "world_war_timeline"; if (safePdfTitle.length > 50) safePdfTitle = safePdfTitle.substring(0, 50); pdf.save(safePdfTitle + '.pdf'); } // Event Listeners tabs.forEach(tab => { tab.addEventListener('click', (e) => switchTab(e.currentTarget.dataset.tab)); }); document.querySelectorAll('.wwtc-next-tab, .wwtc-prev-tab').forEach(button => { button.addEventListener('click', (e) => { const targetTabId = e.currentTarget.dataset.nexttab || e.currentTarget.dataset.prevtab; if (targetTabId) switchTab(targetTabId); }); }); if (addEventForm) addEventForm.addEventListener('submit', handleAddEventFormSubmit); if (clearFormButton) clearFormButton.addEventListener('click', () => { addEventForm.reset(); eventYearInput.focus(); }); [timelineTitleInput, primaryColorInput, textColorInput, bgColorInput, eventCardBgColorInput].forEach(input => { if (input) { input.addEventListener('input', renderTimelinePreview); if (input.type === 'color') input.addEventListener('change', renderTimelinePreview); } }); if (downloadPdfButton && !downloadPdfButton.disabled) { downloadPdfButton.addEventListener('click', handlePdfDownload); } // Initialization loadEventsFromLocalStorage(); updateDatalistSuggestions(); renderCurrentEventsList(); switchTab('eventManager'); // Initial active tab renderTimelinePreview(); // Initial render for preview tab (even if not active, prepares content) updateCssVariables(); });
Scroll to Top