Travel Route Planner For Historical Landmarks

Plan Your Historical Landmark Route

Please select a city first.

Your Suggested Route:

Select landmarks and generate a route to see it here.

Landmark Information

Select a city and generate a route to see landmark details, or view all landmarks for the selected city if no route is active.

Distance to next: (unable to calculate)

`; } } } itemDiv.innerHTML = `

${i + 1}. ${landmark.name || "Unknown Landmark"}

${landmark.description || "No description available."}

Coordinates: Lat: ${(landmark.lat !== undefined ? landmark.lat.toFixed(4) : "N/A")}, Lon: ${(landmark.lon !== undefined ? landmark.lon.toFixed(4) : "N/A")}

${distanceToNextText} `; routeOutputDiv.appendChild(itemDiv); } if (!isNaN(totalKmDistance)) { const totalDisplayDistance = hrp_currentUnit === 'miles' ? (totalKmDistance * 0.621371).toFixed(2) + " mi" : totalKmDistance.toFixed(2) + " km"; totalDistanceDiv.textContent = `Total Estimated Route Distance (as the crow flies): ${totalDisplayDistance}`; } else { totalDistanceDiv.textContent = `Total Estimated Route Distance (as the crow flies): Unable to calculate`; } console.log("hrp_displayRoute: Function finished rendering."); } function hrp_updateLandmarkDetailsTab(clear = false) { console.log("hrp_updateLandmarkDetailsTab: Function called. Clear flag:", clear); const detailsArea = document.getElementById('landmarkDetailsArea'); if (!detailsArea) { console.error("hrp_updateLandmarkDetailsTab: 'landmarkDetailsArea' div NOT FOUND!"); return; } detailsArea.innerHTML = ''; let landmarksToShow = []; if (clear) { detailsArea.innerHTML = '

Please select a city first.

'; return; } if (hrp_currentRoute && hrp_currentRoute.length > 0) { landmarksToShow = hrp_currentRoute; detailsArea.innerHTML = '

Details for Landmarks in Your Route:

'; } else if (hrp_currentCityData && hrp_currentCityData.length > 0) { landmarksToShow = hrp_currentCityData; detailsArea.innerHTML = '

All Landmarks in Selected City:

'; } else { detailsArea.innerHTML = '

Select a city to see landmark details.

'; return; } if(landmarksToShow.length === 0) { detailsArea.innerHTML += '

No landmark data to display.

'; return; } landmarksToShow.forEach(landmark => { if (!landmark) { console.warn("hrp_updateLandmarkDetailsTab: Skipping an undefined landmark in landmarksToShow."); return; } const itemDiv = document.createElement('div'); itemDiv.className = 'hrp-detail-item'; itemDiv.innerHTML = `

${landmark.name || "Unknown Landmark"}

${landmark.description || "No description available."}

Coordinates: Lat: ${(landmark.lat !== undefined ? landmark.lat.toFixed(4) : "N/A")}, Lon: ${(landmark.lon !== undefined ? landmark.lon.toFixed(4) : "N/A")}

`; detailsArea.appendChild(itemDiv); }); console.log("hrp_updateLandmarkDetailsTab: Function finished."); } function hrp_openTab(evt, tabName) { console.log(`hrp_openTab: Called for tabName = ${tabName}. Event object:`, evt); let tabcontent, tablinks; tabcontent = document.querySelectorAll("#historicalRoutePlannerApp .hrp-tab-content"); tabcontent.forEach(tc => tc.style.display = "none"); tablinks = document.querySelectorAll("#historicalRoutePlannerApp .hrp-tab-button"); tablinks.forEach(tl => tl.classList.remove("active")); const currentTabDiv = document.getElementById(tabName); if (currentTabDiv) { currentTabDiv.style.display = "block"; console.log(`hrp_openTab: Set display for ${tabName} to block.`); } else { console.error(`hrp_openTab: Could not find tab content div for ${tabName}.`); } let targetButton; if (evt && evt.currentTarget) { // If called by a click event targetButton = evt.currentTarget; } else { // If called programmatically (evt is null) targetButton = Array.from(tablinks).find(button => { const onclickAttr = button.getAttribute('onclick'); return onclickAttr && onclickAttr.includes(`'${tabName}'`); }); } if (targetButton) { targetButton.classList.add("active"); hrp_currentTabIndex = Array.from(tablinks).indexOf(targetButton); console.log(`hrp_openTab: Activated button for ${tabName}. New index: ${hrp_currentTabIndex}`); } else { console.warn(`hrp_openTab: Could not find or activate button for ${tabName}.`); } } function hrp_navigateTabs(direction) { const tablinks = document.querySelectorAll("#historicalRoutePlannerApp .hrp-tab-button"); if (tablinks.length === 0) return; let newIndex = hrp_currentTabIndex + direction; if (newIndex >= tablinks.length) newIndex = 0; else if (newIndex < 0) newIndex = tablinks.length - 1; // Simulate a click event object for hrp_openTab const targetButton = tablinks[newIndex]; if (targetButton) { // To properly call hrp_openTab, we need the tabName string. // We can extract it from the onclick attribute or have a data attribute on the button. // Example: Extracting from onclick: const onclickAttr = targetButton.getAttribute('onclick'); // e.g., "hrp_openTab(event, 'plannerTab')" const match = onclickAttr.match(/hrp_openTab\(event, '([^']*)'\)/); if (match && match[1]) { const tabName = match[1]; hrp_openTab({ currentTarget: targetButton }, tabName); // Simulate event object } else { console.error("hrp_navigateTabs: Could not extract tabName from button's onclick attribute."); } } } function hrp_downloadPdf() { console.log("hrp_downloadPdf: Function called."); const { jsPDF } = window.jspdf; const doc = new jsPDF(); const titleColor = '#607D8B'; const accentColor = '#FFC107'; const textColor = '#263238'; const headerBgColor = '#607D8B'; const headerTextColor = '#FFFFFF'; let yPos = 20; const city = document.getElementById('citySelect').value || "Not Selected"; doc.setFont('helvetica', 'bold'); doc.setTextColor(titleColor); doc.setFontSize(18); doc.text(`Historical Landmark Route for ${city}`, 14, yPos); yPos += 10; if (!hrp_currentRoute || hrp_currentRoute.length === 0) { doc.setFont('helvetica', 'normal'); doc.setTextColor(textColor); doc.setFontSize(12); doc.text("No route has been generated to download.", 14, yPos); doc.save(`historical_route_plan_${city.replace(/[^a-zA-Z0-9]/g, '_')}.pdf`); console.info("hrp_downloadPdf: No route generated."); return; } const tableData = []; let totalKmDistance = 0; hrp_currentRoute.forEach((landmark, index) => { if (!landmark) return; let distanceToNextKm = NaN; if (index < hrp_currentRoute.length - 1) { const nextLandmark = hrp_currentRoute[index+1]; if (nextLandmark) { distanceToNextKm = hrp_getDistance(landmark.lat, landmark.lon, nextLandmark.lat, nextLandmark.lon); if(!isNaN(distanceToNextKm)) totalKmDistance += distanceToNextKm; } } const distDisplay = isNaN(distanceToNextKm) ? "N/A" : (hrp_currentUnit === 'miles' ? (distanceToNextKm * 0.621371).toFixed(2) + " mi" : distanceToNextKm.toFixed(2) + " km"); tableData.push([ `${index + 1}. ${landmark.name || "N/A"}`, landmark.description || "N/A", `Lat: ${(landmark.lat !== undefined ? landmark.lat.toFixed(4) : "N/A")}, Lon: ${(landmark.lon !== undefined ? landmark.lon.toFixed(4) : "N/A")}`, (index < hrp_currentRoute.length - 1) ? distDisplay : "-" ]); }); doc.autoTable({ startY: yPos, head: [['Stop', 'Landmark & Description', 'Coordinates', 'Dist. to Next']], body: tableData, theme: 'grid', headStyles: { fillColor: headerBgColor, textColor: headerTextColor, fontStyle: 'bold' }, styles: { font: 'helvetica', fontSize: 9, cellPadding: 2.5, textColor: textColor, valign: 'middle' }, columnStyles: { 0: { cellWidth: 45 }, 1: { cellWidth: 'auto' }, 2: { cellWidth: 35 }, 3: { cellWidth: 25 } }, didDrawPage: function (data) { yPos = data.cursor.y + 10; } }); if (doc.lastAutoTable && doc.lastAutoTable.finalY) { yPos = doc.lastAutoTable.finalY + 10; } doc.setFont('helvetica', 'bold'); doc.setTextColor(accentColor); doc.setFontSize(12); const totalDisplayDistance = isNaN(totalKmDistance) ? "Unable to calculate" : (hrp_currentUnit === 'miles' ? (totalKmDistance * 0.621371).toFixed(2) + " mi" : totalKmDistance.toFixed(2) + " km"); doc.text(`Total Estimated Route Distance (as the crow flies): ${totalDisplayDistance}`, 14, yPos); doc.save(`historical_route_plan_${city.replace(/[^a-zA-Z0-9]/g, '_')}.pdf`); console.log("hrp_downloadPdf: Function finished."); } document.addEventListener('DOMContentLoaded', function() { console.log("DOM fully loaded and parsed. Initializing tool."); try { hrp_initCitySelector(); hrp_populateLandmarks(); const firstTabButton = document.querySelector("#historicalRoutePlannerApp .hrp-tab-button"); if (firstTabButton) { // Get the tabName from the first button's onclick attribute for robust initial tab opening const onclickAttr = firstTabButton.getAttribute('onclick'); const match = onclickAttr.match(/hrp_openTab\(event, '([^']*)'\)/); if (match && match[1]) { const initialTabName = match[1]; hrp_openTab({ currentTarget: firstTabButton }, initialTabName); } else { console.warn("DOMContentLoaded: Could not determine initial tab name from first button."); firstTabButton.click(); // Fallback to direct click if parsing fails } } else { console.warn("DOMContentLoaded: First tab button not found for initial setup."); } console.log("DOMContentLoaded: Tool initialization complete."); } catch (e) { console.error("DOMContentLoaded: Error during setup:", e); } });
Scroll to Top