Fix: Clean up map_iframe_single.html, remove debug overlay, ensure clean map rendering.
This commit is contained in:
345
app/static/map_iframe.html
Normal file
345
app/static/map_iframe.html
Normal file
@@ -0,0 +1,345 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Adventure Routes Map</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#map {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.map-loading {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 1000;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border: 3px solid #f3f3f3;
|
||||
border-top: 3px solid #f97316;
|
||||
border-radius: 50%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto 10px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.route-popup {
|
||||
min-width: 250px;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.route-popup h3 {
|
||||
margin: 0 0 10px 0;
|
||||
color: #1f2937;
|
||||
font-size: 1.1em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.route-popup .stat {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 5px 0;
|
||||
padding: 2px 0;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.route-popup .stat:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.route-popup .stat strong {
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.route-popup .view-btn {
|
||||
display: inline-block;
|
||||
margin-top: 10px;
|
||||
padding: 8px 16px;
|
||||
background: linear-gradient(45deg, #f97316, #ea580c);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9em;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.route-popup .view-btn:hover {
|
||||
background: linear-gradient(45deg, #ea580c, #dc2626);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.map-controls {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.map-control-btn {
|
||||
background: white;
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 6px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: all 0.2s;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.map-control-btn:hover {
|
||||
background: #f3f4f6;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.map-control-btn.active {
|
||||
background: #f97316;
|
||||
color: white;
|
||||
border-color: #ea580c;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map">
|
||||
<div id="map-loading" class="map-loading">
|
||||
<div class="spinner"></div>
|
||||
<div>Loading adventure routes...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Map Controls -->
|
||||
<div class="map-controls">
|
||||
<button id="fit-routes" class="map-control-btn" title="Fit all routes">🎯</button>
|
||||
<button id="toggle-routes" class="map-control-btn active" title="Toggle routes">🛣️</button>
|
||||
<button id="refresh-map" class="map-control-btn" title="Refresh map">🔄</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let map;
|
||||
let routeLayer;
|
||||
let routesVisible = true;
|
||||
|
||||
function initializeMap() {
|
||||
console.log('Initializing standalone map...');
|
||||
|
||||
// Romania center and zoom for default view
|
||||
const romaniaCenter = [45.9432, 24.9668]; // Center of Romania
|
||||
const romaniaZoom = 7;
|
||||
// Create map
|
||||
map = L.map('map', {
|
||||
zoomControl: true,
|
||||
scrollWheelZoom: true,
|
||||
doubleClickZoom: true,
|
||||
touchZoom: true
|
||||
}).setView(romaniaCenter, romaniaZoom);
|
||||
|
||||
// Add OpenStreetMap tiles
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||
maxZoom: 18,
|
||||
minZoom: 5
|
||||
}).addTo(map);
|
||||
|
||||
console.log('Base map created');
|
||||
|
||||
// Create route layer group
|
||||
routeLayer = L.layerGroup().addTo(map);
|
||||
|
||||
// Load routes
|
||||
loadRoutes();
|
||||
|
||||
// Setup controls
|
||||
setupControls();
|
||||
}
|
||||
|
||||
function loadRoutes() {
|
||||
console.log('Loading routes from API...');
|
||||
|
||||
// Get the parent window's origin for API calls
|
||||
const apiUrl = window.location.origin + '/community/api/routes';
|
||||
|
||||
fetch(apiUrl)
|
||||
.then(response => {
|
||||
console.log('API response status:', response.status);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(routesData => {
|
||||
console.log(`Loaded ${routesData.length} routes`);
|
||||
|
||||
// Hide loading indicator
|
||||
const loading = document.getElementById('map-loading');
|
||||
if (loading) {
|
||||
loading.style.display = 'none';
|
||||
}
|
||||
|
||||
if (routesData.length === 0) {
|
||||
console.log('No routes found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Route colors
|
||||
const colors = [
|
||||
'#f97316', '#dc2626', '#059669', '#7c3aed',
|
||||
'#db2777', '#2563eb', '#7c2d12', '#065f46'
|
||||
];
|
||||
|
||||
const allBounds = [];
|
||||
|
||||
// Add each route
|
||||
routesData.forEach((route, index) => {
|
||||
if (route.coordinates && route.coordinates.length > 0) {
|
||||
const color = colors[index % colors.length];
|
||||
|
||||
// Create polyline
|
||||
const polyline = L.polyline(route.coordinates, {
|
||||
color: color,
|
||||
weight: 4,
|
||||
opacity: 0.8,
|
||||
smoothFactor: 1
|
||||
});
|
||||
|
||||
// Create popup content
|
||||
const popupContent = `
|
||||
<div class="route-popup">
|
||||
<h3>🏍️ ${route.title}</h3>
|
||||
<div class="stat">
|
||||
<span>👤 Author:</span>
|
||||
<strong>${route.author}</strong>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span>📏 Distance:</span>
|
||||
<strong>${route.distance.toFixed(2)} km</strong>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span>⛰️ Elevation Gain:</span>
|
||||
<strong>${route.elevation_gain.toFixed(0)} m</strong>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span>🏔️ Max Elevation:</span>
|
||||
<strong>${route.max_elevation.toFixed(0)} m</strong>
|
||||
</div>
|
||||
<a href="${route.url}" target="_parent" class="view-btn">
|
||||
🔍 View Adventure Details
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
polyline.bindPopup(popupContent);
|
||||
|
||||
// Add to route layer
|
||||
routeLayer.addLayer(polyline);
|
||||
|
||||
// Collect bounds for fitting
|
||||
allBounds.push(...route.coordinates);
|
||||
|
||||
console.log(`Added route: ${route.title} (${route.coordinates.length} points)`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Successfully loaded ${routesData.length} routes`);
|
||||
|
||||
// Do NOT auto-fit map to routes on load; keep Romania view/zoom
|
||||
// Only fit to routes when user clicks the 🎯 button
|
||||
// (see setupControls)
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading routes:', error);
|
||||
|
||||
const loading = document.getElementById('map-loading');
|
||||
if (loading) {
|
||||
loading.innerHTML = `
|
||||
<div style="color: #dc2626;">
|
||||
<div style="font-size: 1.2em; margin-bottom: 8px;">⚠️</div>
|
||||
<div>Failed to load routes</div>
|
||||
<div style="font-size: 0.8em; margin-top: 5px; color: #6b7280;">
|
||||
${error.message}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setupControls() {
|
||||
// Fit routes button
|
||||
document.getElementById('fit-routes').addEventListener('click', () => {
|
||||
if (routeLayer.getLayers().length > 0) {
|
||||
const group = new L.FeatureGroup();
|
||||
routeLayer.eachLayer(layer => group.addLayer(layer));
|
||||
map.fitBounds(group.getBounds(), { padding: [20, 20] });
|
||||
}
|
||||
});
|
||||
|
||||
// Toggle routes button
|
||||
document.getElementById('toggle-routes').addEventListener('click', (e) => {
|
||||
if (routesVisible) {
|
||||
map.removeLayer(routeLayer);
|
||||
e.target.classList.remove('active');
|
||||
routesVisible = false;
|
||||
} else {
|
||||
map.addLayer(routeLayer);
|
||||
e.target.classList.add('active');
|
||||
routesVisible = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Refresh map button
|
||||
document.getElementById('refresh-map').addEventListener('click', () => {
|
||||
routeLayer.clearLayers();
|
||||
loadRoutes();
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initializeMap);
|
||||
} else {
|
||||
initializeMap();
|
||||
}
|
||||
|
||||
// Handle resize
|
||||
window.addEventListener('resize', () => {
|
||||
if (map) {
|
||||
setTimeout(() => map.invalidateSize(), 100);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
99
app/static/map_iframe_single.html
Normal file
99
app/static/map_iframe_single.html
Normal file
@@ -0,0 +1,99 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Route Map (Debug)</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin=""/>
|
||||
<style>
|
||||
html, body { height: 100%; margin: 0; padding: 0; }
|
||||
#map { width: 100vw; height: 100vh; min-height: 100%; min-width: 100%; border-radius: 1rem; }
|
||||
.leaflet-container { background: #f8f9fa; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
|
||||
<script>
|
||||
// Get route_id from query string
|
||||
function getRouteId() {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
return params.get('route_id');
|
||||
}
|
||||
|
||||
const routeId = getRouteId();
|
||||
const map = L.map('map');
|
||||
|
||||
// Set map size to fit iframe
|
||||
function resizeMap() {
|
||||
const mapDiv = document.getElementById('map');
|
||||
mapDiv.style.width = window.innerWidth + 'px';
|
||||
mapDiv.style.height = window.innerHeight + 'px';
|
||||
map.invalidateSize();
|
||||
}
|
||||
window.addEventListener('resize', resizeMap);
|
||||
|
||||
// Initial size
|
||||
resizeMap();
|
||||
|
||||
// Add OSM tiles
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© OpenStreetMap contributors'
|
||||
}).addTo(map);
|
||||
|
||||
// Fetch route data
|
||||
if (routeId) {
|
||||
fetch(`/community/api/route/${routeId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data && data.coordinates && data.coordinates.length > 0) {
|
||||
const latlngs = data.coordinates.map(pt => [pt[1], pt[0]]);
|
||||
const polyline = L.polyline(latlngs, { color: '#ef4444', weight: 5, opacity: 0.9 }).addTo(map);
|
||||
map.fitBounds(polyline.getBounds(), { padding: [20, 20], maxZoom: 15 });
|
||||
// Start marker
|
||||
L.marker(latlngs[0], { icon: L.divIcon({ html: '<div style="background:#22c55e;border-radius:50%;width:24px;height:24px;display:flex;align-items:center;justify-content:center;color:#fff;"><i class=\'fas fa-play\'></i></div>', className: 'custom-div-icon', iconSize: [24,24], iconAnchor: [12,12] }) }).addTo(map);
|
||||
// End marker
|
||||
L.marker(latlngs[latlngs.length-1], { icon: L.divIcon({ html: '<div style="background:#ef4444;border-radius:50%;width:24px;height:24px;display:flex;align-items:center;justify-content:center;color:#fff;"><i class=\'fas fa-flag-checkered\'></i></div>', className: 'custom-div-icon', iconSize: [24,24], iconAnchor: [12,12] }) }).addTo(map);
|
||||
} else {
|
||||
map.setView([45.9432, 24.9668], 6);
|
||||
L.marker([45.9432, 24.9668]).addTo(map).bindPopup('No route data').openPopup();
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
map.setView([45.9432, 24.9668], 6);
|
||||
L.marker([45.9432, 24.9668]).addTo(map).bindPopup('Error loading route').openPopup();
|
||||
});
|
||||
} else {
|
||||
map.setView([45.9432, 24.9668], 6);
|
||||
L.marker([45.9432, 24.9668]).addTo(map).bindPopup('No route selected').openPopup();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
color: '#f97316', weight: 5, opacity: 0.9, smoothFactor: 1
|
||||
}).addTo(routeLayer);
|
||||
polyline.bindPopup(`<div><h3>🏍️ ${route.title}</h3><div>Distance: ${route.distance.toFixed(2)} km</div><div>Elevation Gain: ${route.elevation_gain.toFixed(0)} m</div></div>`);
|
||||
// Always fit bounds to the route and bind to frame size
|
||||
function fitRouteBounds() {
|
||||
map.invalidateSize();
|
||||
map.fitBounds(polyline.getBounds(), { padding: [10, 10], maxZoom: 18 });
|
||||
}
|
||||
fitRouteBounds();
|
||||
window.addEventListener('resize', fitRouteBounds);
|
||||
})
|
||||
.catch(error => showError(error.message));
|
||||
}
|
||||
function showError(msg) {
|
||||
const loading = document.getElementById('map-loading');
|
||||
loading.innerHTML = `<div style='color:#dc2626;'><div style='font-size:1.2em;margin-bottom:8px;'>⚠️</div><div>${msg}</div></div>`;
|
||||
}
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initializeMap);
|
||||
} else {
|
||||
initializeMap();
|
||||
}
|
||||
window.addEventListener('resize', () => { if (map) setTimeout(() => map.invalidateSize(), 100); });
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user