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

No monument records added yet.

'; return; } const ul = document.createElement('ul'); const sortedRecords = [...monumentRecords].sort((a,b) => a.monumentName.localeCompare(b.monumentName)); sortedRecords.forEach(record => { const li = document.createElement('li'); const text = document.createElement('span'); text.textContent = `${record.monumentName} (${record.locationCityCountry || 'N/A'})`; const delBtn = document.createElement('button'); delBtn.textContent = 'Delete'; delBtn.classList.add('hmia-button', 'hmia-button-delete'); delBtn.addEventListener('click', () => deleteRecord(record.id)); li.appendChild(text); li.appendChild(delBtn); ul.appendChild(li); }); currentRecordsListDiv.appendChild(ul); } function handleAddRecordFormSubmit(event) { event.preventDefault(); const newRecord = { id: generateId(), monumentName: monumentNameInput.value.trim(), locationCityCountry: locationInput.value.trim(), periodBuilt: periodBuiltInput.value.trim(), archStyle: archStyleInput.value.trim(), keyFeatures: keyFeaturesInput.value.trim(), historicalSignificance: significanceInput.value.trim(), materialsUsed: materialsInput.value.trim(), visitorInformation: visitorInfoInput.value.trim(), imageURL: imageUrlInput.value.trim() }; if (!newRecord.monumentName || !newRecord.locationCityCountry) { alert("Monument Name and Location are required fields."); return; } monumentRecords.push(newRecord); saveRecordsToLocalStorage(); renderCurrentRecordsList(); updateArchStyleSuggestions(); addRecordForm.reset(); monumentNameInput.focus(); if (document.getElementById('browseExport').classList.contains('active')) renderBrowseView(); } function deleteRecord(recordId) { monumentRecords = monumentRecords.filter(r => r.id !== recordId); saveRecordsToLocalStorage(); renderCurrentRecordsList(); updateArchStyleSuggestions(); if (document.getElementById('browseExport').classList.contains('active')) renderBrowseView(); } function getFilteredRecords() { let records = [...monumentRecords]; const styleFilter = filterStyleSelect.value; const locationKeyword = filterLocationInput.value.toLowerCase(); const generalKeyword = filterKeywordInput.value.toLowerCase(); if (styleFilter) records = records.filter(r => r.archStyle === styleFilter); if (locationKeyword) records = records.filter(r => r.locationCityCountry.toLowerCase().includes(locationKeyword)); if (generalKeyword) { records = records.filter(r => r.monumentName.toLowerCase().includes(generalKeyword) || r.keyFeatures.toLowerCase().includes(generalKeyword) || r.historicalSignificance.toLowerCase().includes(generalKeyword) ); } // Default sort by name records.sort((a,b) => a.monumentName.localeCompare(b.monumentName)); return records; } function renderBrowseView() { updateCssVariables(); browseRecordsViewDiv.innerHTML = ''; const filteredRecords = getFilteredRecords(); if (filteredRecords.length === 0) { browseRecordsViewDiv.innerHTML = '

No records match your criteria or none have been added.

'; return; } filteredRecords.forEach(record => { const card = document.createElement('div'); card.classList.add('hmia-record-card'); let detailsHtml = ''; if(record.periodBuilt) detailsHtml += `

Period Built: ${record.periodBuilt}

`; if(record.archStyle) detailsHtml += `

Architectural Style: ${record.archStyle}

`; if(record.keyFeatures) detailsHtml += `

Key Features: ${record.keyFeatures.replace(/\n/g, '
')}

`; if(record.historicalSignificance) detailsHtml += `

Historical Significance: ${record.historicalSignificance.replace(/\n/g, '
')}

`; if(record.materialsUsed) detailsHtml += `

Materials Used: ${record.materialsUsed}

`; if(record.visitorInformation) detailsHtml += `

Visitor Info: ${record.visitorInformation.replace(/\n/g, '
')}

`; if(record.imageURL) detailsHtml += `

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(); });
Scroll to Top