Historical Monuments Identifier
Manage Historical Monument Records
Add New Monument Record
My Monument Records (0)
No monument records added yet.
Browse, Identify & Export Monument Records
Identify & Filter Records
Customize Appearance & PDF
My Historical Monuments Collection
Materials Used: ${record.materialsUsed}
`; if(record.visitorInformation) detailsHtml += `Visitor Info: ${record.visitorInformation.replace(/\n/g, '
')}
Image URL: ${record.imageURL}
`; card.innerHTML = `${record.monumentName}
${record.locationCityCountry}
${detailsHtml} `; browseRecordsViewDiv.appendChild(card); }); } function handlePdfDownload() { if (!jsPDF_constructor_for_tool) { alert("PDF library not available."); return; } const recordsToExport = getFilteredRecords(); const pdfDocTitle = displayTitleInput.value; if (recordsToExport.length === 0) { alert("No records 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(pdfDocTitle, contentWidth); pdf.text(titleLines, pdf.internal.pageSize.getWidth() / 2, currentY, { align: 'center' }); currentY += (titleLines.length * 18 * 0.35) + 10; recordsToExport.forEach(record => { let estimatedBlockHeight = 0; // Basic height estimation pdf.setFontSize(14); estimatedBlockHeight += 6; // Name pdf.setFontSize(10); estimatedBlockHeight += 4; // Location // Add more for other fields if(record.periodBuilt) estimatedBlockHeight +=4; if(record.archStyle) estimatedBlockHeight +=4; if(record.keyFeatures) estimatedBlockHeight += pdf.splitTextToSize(record.keyFeatures, contentWidth).length * 3.5; if(record.historicalSignificance) estimatedBlockHeight += pdf.splitTextToSize(record.historicalSignificance, contentWidth).length * 3.5; estimatedBlockHeight += 10; // Spacing if (currentY + estimatedBlockHeight > pdf.internal.pageSize.getHeight() - margin) { pdf.addPage(); currentY = margin; pdf.setFillColor(pageBgColor); pdf.rect(0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight(), 'F'); } pdf.setFontSize(14); pdf.setTextColor(primaryColor); pdf.setFont("helvetica", "bold"); const nameLines = pdf.splitTextToSize(record.monumentName, contentWidth); pdf.text(nameLines, margin, currentY); currentY += (nameLines.length * 14 * 0.35) + 2; pdf.setFontSize(10); pdf.setTextColor(textColor); pdf.setFont("helvetica", "italic"); pdf.text(record.locationCityCountry, margin, currentY); currentY += (10 * 0.35) + 4; pdf.setFont("helvetica", "normal"); const renderPdfSection = (label, text, isMultiLine = false) => { if (text) { pdf.setFontSize(9); pdf.setTextColor(primaryColor); pdf.setFont("helvetica", "bold"); pdf.text(label + ":", margin, currentY); pdf.setFontSize(9); pdf.setTextColor(textColor); pdf.setFont("helvetica", "normal"); const labelWidth = pdf.getStringUnitWidth(label + ":") * 9 / pdf.internal.scaleFactor + 2; const textLines = pdf.splitTextToSize(text, contentWidth - labelWidth); pdf.text(textLines, margin + labelWidth, currentY); currentY += (textLines.length * 9 * 0.35) + (isMultiLine ? 3 : 2); } }; renderPdfSection("Period Built", record.periodBuilt); renderPdfSection("Architectural Style", record.archStyle); renderPdfSection("Key Features", record.keyFeatures, true); renderPdfSection("Historical Significance", record.historicalSignificance, true); renderPdfSection("Materials Used", record.materialsUsed); renderPdfSection("Visitor Info", record.visitorInformation, true); if (record.imageURL) { pdf.setFontSize(8); pdf.setTextColor("#007bff"); // Link color pdf.textWithLink("Image Link (click to try opening)", margin, currentY, {url: record.imageURL}); currentY += 8; } currentY += 6; // Space between records }); let safePdfTitle = pdfDocTitle.replace(/[^a-z0-9]/gi, '_').toLowerCase() || "historical_monuments"; 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('.hmia-next-tab, .hmia-prev-tab').forEach(button => { button.addEventListener('click', (e) => { const targetTabId = e.currentTarget.dataset.nexttab || e.currentTarget.dataset.prevtab; if (targetTabId) switchTab(targetTabId); }); }); if (addRecordForm) addRecordForm.addEventListener('submit', handleAddRecordFormSubmit); if (clearFormButton) clearFormButton.addEventListener('click', () => addRecordForm.reset()); if(applyFiltersButton) applyFiltersButton.addEventListener('click', renderBrowseView); if(clearFiltersButton) clearFiltersButton.addEventListener('click', () => { filterStyleSelect.value = ''; filterLocationInput.value = ''; filterKeywordInput.value = ''; renderBrowseView(); }); // Live filtering for keyword inputs can be performance intensive on large lists, so keeping it to button click for now. // Add listeners to filter inputs if live filtering is desired: // filterLocationInput.addEventListener('input', renderBrowseView); // filterKeywordInput.addEventListener('input', renderBrowseView); // filterStyleSelect.addEventListener('change', renderBrowseView); [displayTitleInput, primaryColorInput, textColorInput, bgColorInput, cardBgColorInput].forEach(input => { if (input) { const updateAndRender = () => { updateCssVariables(); renderBrowseView(); }; input.addEventListener('input', updateAndRender); if (input.type === 'color') input.addEventListener('change', updateAndRender); } }); if (downloadPdfButton && !downloadPdfButton.disabled) { downloadPdfButton.addEventListener('click', handlePdfDownload); } // Initialization loadRecordsFromLocalStorage(); updateArchStyleSuggestions(); renderCurrentRecordsList(); switchTab('manageRecords'); renderBrowseView(); updateCssVariables(); });