mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-05 23:00:16 +00:00
Add interactive biblical maps feature
This commit is contained in:
@@ -0,0 +1,540 @@
|
||||
/**
|
||||
* Biblical Maps - Interactive maps for KJV Study
|
||||
* Uses OpenStreetMap with Leaflet.js (free, no API key required)
|
||||
*/
|
||||
|
||||
class BiblicalMaps {
|
||||
constructor() {
|
||||
this.map = null;
|
||||
this.currentMarkers = [];
|
||||
this.currentLayer = null;
|
||||
this.biblicalLocations = this.getBiblicalLocations();
|
||||
this.mapLayers = this.getMapLayers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the map
|
||||
*/
|
||||
init(containerId, options = {}) {
|
||||
const defaultCenter = [31.7683, 35.2137]; // Jerusalem
|
||||
const defaultZoom = 7;
|
||||
|
||||
this.map = L.map(containerId, {
|
||||
center: options.center || defaultCenter,
|
||||
zoom: options.zoom || defaultZoom,
|
||||
zoomControl: true,
|
||||
scrollWheelZoom: true,
|
||||
doubleClickZoom: true,
|
||||
boxZoom: true,
|
||||
keyboard: true,
|
||||
dragging: true,
|
||||
touchZoom: true
|
||||
});
|
||||
|
||||
// Add default OpenStreetMap layer
|
||||
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: 3
|
||||
}).addTo(this.map);
|
||||
|
||||
// Add layer control
|
||||
this.addLayerControl();
|
||||
|
||||
// Add biblical locations
|
||||
this.addBiblicalLocations();
|
||||
|
||||
return this.map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add layer control for different map types
|
||||
*/
|
||||
addLayerControl() {
|
||||
const baseLayers = {
|
||||
"OpenStreetMap": L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
"Terrain": L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://opentopomap.org">OpenTopoMap</a> contributors'
|
||||
}),
|
||||
"Satellite": L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
||||
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
||||
})
|
||||
};
|
||||
|
||||
L.control.layers(baseLayers, this.mapLayers).addTo(this.map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get map overlay layers for different biblical periods
|
||||
*/
|
||||
getMapLayers() {
|
||||
const layers = {};
|
||||
|
||||
// Create marker groups for different periods
|
||||
layers["Old Testament Cities"] = L.layerGroup();
|
||||
layers["New Testament Cities"] = L.layerGroup();
|
||||
layers["Paul's Journeys"] = L.layerGroup();
|
||||
layers["Tribal Territories"] = L.layerGroup();
|
||||
layers["Major Events"] = L.layerGroup();
|
||||
|
||||
return layers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Biblical locations with coordinates and information
|
||||
*/
|
||||
getBiblicalLocations() {
|
||||
return {
|
||||
// Major Old Testament Cities
|
||||
jerusalem: {
|
||||
name: "Jerusalem",
|
||||
coords: [31.7683, 35.2137],
|
||||
type: "city",
|
||||
period: ["ot", "nt"],
|
||||
description: "The holy city, site of Solomon's Temple and Jesus's crucifixion",
|
||||
verses: ["2 Samuel 5:6-7", "1 Kings 6:1", "Matthew 27:33"],
|
||||
layer: ["Old Testament Cities", "New Testament Cities"]
|
||||
},
|
||||
bethlehem: {
|
||||
name: "Bethlehem",
|
||||
coords: [31.7054, 35.2024],
|
||||
type: "city",
|
||||
period: ["ot", "nt"],
|
||||
description: "City of David's birth and Jesus's birth",
|
||||
verses: ["1 Samuel 16:1", "Micah 5:2", "Matthew 2:1"],
|
||||
layer: ["Old Testament Cities", "New Testament Cities"]
|
||||
},
|
||||
nazareth: {
|
||||
name: "Nazareth",
|
||||
coords: [32.7009, 35.2976],
|
||||
type: "city",
|
||||
period: ["nt"],
|
||||
description: "Jesus's hometown",
|
||||
verses: ["Matthew 2:23", "Luke 1:26", "Luke 4:16"],
|
||||
layer: ["New Testament Cities"]
|
||||
},
|
||||
capernaum: {
|
||||
name: "Capernaum",
|
||||
coords: [32.8819, 35.5747],
|
||||
type: "city",
|
||||
period: ["nt"],
|
||||
description: "Jesus's ministry headquarters",
|
||||
verses: ["Matthew 4:13", "Matthew 8:5", "Mark 2:1"],
|
||||
layer: ["New Testament Cities"]
|
||||
},
|
||||
jericho: {
|
||||
name: "Jericho",
|
||||
coords: [31.8667, 35.4444],
|
||||
type: "city",
|
||||
period: ["ot", "nt"],
|
||||
description: "First city conquered by Joshua",
|
||||
verses: ["Joshua 6:1-27", "Luke 19:1"],
|
||||
layer: ["Old Testament Cities", "New Testament Cities"]
|
||||
},
|
||||
damascus: {
|
||||
name: "Damascus",
|
||||
coords: [33.5138, 36.2765],
|
||||
type: "city",
|
||||
period: ["ot", "nt"],
|
||||
description: "Ancient city, site of Paul's conversion",
|
||||
verses: ["2 Kings 5:12", "Acts 9:3"],
|
||||
layer: ["Old Testament Cities", "Paul's Journeys"]
|
||||
},
|
||||
babylon: {
|
||||
name: "Babylon",
|
||||
coords: [32.5355, 44.4275],
|
||||
type: "city",
|
||||
period: ["ot"],
|
||||
description: "Capital of Babylonian Empire, site of exile",
|
||||
verses: ["2 Kings 25:11", "Psalm 137:1", "Daniel 1:1"],
|
||||
layer: ["Old Testament Cities"]
|
||||
},
|
||||
egypt_memphis: {
|
||||
name: "Memphis (Egypt)",
|
||||
coords: [29.8467, 31.2500],
|
||||
type: "city",
|
||||
period: ["ot"],
|
||||
description: "Ancient capital of Egypt",
|
||||
verses: ["Isaiah 19:13", "Jeremiah 2:16", "Hosea 9:6"],
|
||||
layer: ["Old Testament Cities"]
|
||||
},
|
||||
mount_sinai: {
|
||||
name: "Mount Sinai",
|
||||
coords: [28.5394, 33.9731],
|
||||
type: "mountain",
|
||||
period: ["ot"],
|
||||
description: "Where Moses received the Ten Commandments",
|
||||
verses: ["Exodus 19:20", "Exodus 24:16", "Deuteronomy 4:10"],
|
||||
layer: ["Major Events"]
|
||||
},
|
||||
mount_carmel: {
|
||||
name: "Mount Carmel",
|
||||
coords: [32.7319, 35.0478],
|
||||
type: "mountain",
|
||||
period: ["ot"],
|
||||
description: "Site of Elijah's contest with Baal's prophets",
|
||||
verses: ["1 Kings 18:19-40"],
|
||||
layer: ["Major Events"]
|
||||
},
|
||||
// Paul's Journey Cities
|
||||
antioch: {
|
||||
name: "Antioch",
|
||||
coords: [36.2012, 36.1611],
|
||||
type: "city",
|
||||
period: ["nt"],
|
||||
description: "First Gentile church, Paul's mission base",
|
||||
verses: ["Acts 11:26", "Acts 13:1"],
|
||||
layer: ["Paul's Journeys"]
|
||||
},
|
||||
athens: {
|
||||
name: "Athens",
|
||||
coords: [37.9755, 23.7348],
|
||||
type: "city",
|
||||
period: ["nt"],
|
||||
description: "Paul preached at the Areopagus",
|
||||
verses: ["Acts 17:16-34"],
|
||||
layer: ["Paul's Journeys"]
|
||||
},
|
||||
corinth: {
|
||||
name: "Corinth",
|
||||
coords: [37.9065, 22.8756],
|
||||
type: "city",
|
||||
period: ["nt"],
|
||||
description: "Paul established church and wrote letters",
|
||||
verses: ["Acts 18:1", "1 Corinthians 1:2"],
|
||||
layer: ["Paul's Journeys"]
|
||||
},
|
||||
ephesus: {
|
||||
name: "Ephesus",
|
||||
coords: [37.9495, 27.3517],
|
||||
type: "city",
|
||||
period: ["nt"],
|
||||
description: "Major center of Paul's ministry",
|
||||
verses: ["Acts 19:1", "Ephesians 1:1", "Revelation 2:1"],
|
||||
layer: ["Paul's Journeys"]
|
||||
},
|
||||
rome: {
|
||||
name: "Rome",
|
||||
coords: [41.9028, 12.4964],
|
||||
type: "city",
|
||||
period: ["nt"],
|
||||
description: "Capital of Roman Empire, Paul's final destination",
|
||||
verses: ["Acts 28:16", "Romans 1:7"],
|
||||
layer: ["Paul's Journeys"]
|
||||
},
|
||||
// Bodies of Water
|
||||
sea_of_galilee: {
|
||||
name: "Sea of Galilee",
|
||||
coords: [32.8219, 35.5881],
|
||||
type: "water",
|
||||
period: ["ot", "nt"],
|
||||
description: "Where Jesus called disciples and performed miracles",
|
||||
verses: ["Matthew 4:18", "Mark 6:47-52", "John 21:1"],
|
||||
layer: ["New Testament Cities", "Major Events"]
|
||||
},
|
||||
dead_sea: {
|
||||
name: "Dead Sea",
|
||||
coords: [31.5590, 35.4732],
|
||||
type: "water",
|
||||
period: ["ot", "nt"],
|
||||
description: "Salt sea, lowest point on earth",
|
||||
verses: ["Genesis 14:3", "Joshua 3:16"],
|
||||
layer: ["Old Testament Cities"]
|
||||
},
|
||||
jordan_river: {
|
||||
name: "Jordan River",
|
||||
coords: [32.0000, 35.5000],
|
||||
type: "water",
|
||||
period: ["ot", "nt"],
|
||||
description: "River where Jesus was baptized",
|
||||
verses: ["Joshua 3:17", "Matthew 3:13", "Mark 1:9"],
|
||||
layer: ["Old Testament Cities", "New Testament Cities"]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all biblical locations to the map
|
||||
*/
|
||||
addBiblicalLocations() {
|
||||
Object.entries(this.biblicalLocations).forEach(([key, location]) => {
|
||||
const marker = this.createLocationMarker(location);
|
||||
|
||||
// Add marker to appropriate layers
|
||||
location.layer.forEach(layerName => {
|
||||
if (this.mapLayers[layerName]) {
|
||||
this.mapLayers[layerName].addLayer(marker);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add all layers to map by default
|
||||
Object.values(this.mapLayers).forEach(layer => {
|
||||
layer.addTo(this.map);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a marker for a biblical location
|
||||
*/
|
||||
createLocationMarker(location) {
|
||||
const icon = this.getLocationIcon(location.type);
|
||||
const marker = L.marker(location.coords, { icon: icon });
|
||||
|
||||
// Create popup content
|
||||
const popupContent = this.createPopupContent(location);
|
||||
marker.bindPopup(popupContent, {
|
||||
maxWidth: 300,
|
||||
className: 'biblical-location-popup'
|
||||
});
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get appropriate icon for location type
|
||||
*/
|
||||
getLocationIcon(type) {
|
||||
const iconConfigs = {
|
||||
city: { color: '#8B4513', icon: '🏛️' },
|
||||
mountain: { color: '#8B7355', icon: '⛰️' },
|
||||
water: { color: '#4682B4', icon: '🌊' },
|
||||
temple: { color: '#DAA520', icon: '🕌' },
|
||||
event: { color: '#DC143C', icon: '✨' }
|
||||
};
|
||||
|
||||
const config = iconConfigs[type] || iconConfigs.city;
|
||||
|
||||
return L.divIcon({
|
||||
html: `<div style="background-color: ${config.color}; border-radius: 50%; width: 25px; height: 25px; display: flex; align-items: center; justify-content: center; border: 2px solid white; box-shadow: 0 2px 4px rgba(0,0,0,0.3);">
|
||||
<span style="font-size: 12px;">${config.icon}</span>
|
||||
</div>`,
|
||||
className: 'biblical-location-marker',
|
||||
iconSize: [25, 25],
|
||||
iconAnchor: [12, 12],
|
||||
popupAnchor: [0, -15]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create popup content for a location
|
||||
*/
|
||||
createPopupContent(location) {
|
||||
const verseLinks = location.verses.map(verse =>
|
||||
`<a href="/search?q=${encodeURIComponent(verse)}" class="verse-link">${verse}</a>`
|
||||
).join(', ');
|
||||
|
||||
return `
|
||||
<div class="biblical-location-info">
|
||||
<h3>${location.name}</h3>
|
||||
<p class="description">${location.description}</p>
|
||||
<div class="verses">
|
||||
<strong>Key Verses:</strong><br>
|
||||
${verseLinks}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a location and center map on it
|
||||
*/
|
||||
searchLocation(locationName) {
|
||||
const normalizedName = locationName.toLowerCase();
|
||||
const location = Object.values(this.biblicalLocations).find(loc =>
|
||||
loc.name.toLowerCase().includes(normalizedName)
|
||||
);
|
||||
|
||||
if (location) {
|
||||
this.map.setView(location.coords, 10);
|
||||
// Find and open the marker popup
|
||||
this.mapLayers.forEach(layer => {
|
||||
layer.eachLayer(marker => {
|
||||
if (marker.getLatLng().lat === location.coords[0] &&
|
||||
marker.getLatLng().lng === location.coords[1]) {
|
||||
marker.openPopup();
|
||||
}
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show locations related to a Bible book
|
||||
*/
|
||||
showBookLocations(bookName) {
|
||||
this.clearHighlights();
|
||||
const relevantLocations = this.getLocationsForBook(bookName);
|
||||
|
||||
relevantLocations.forEach(locationKey => {
|
||||
const location = this.biblicalLocations[locationKey];
|
||||
if (location) {
|
||||
// Add highlight to marker
|
||||
this.highlightLocation(location);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get locations relevant to a specific Bible book
|
||||
*/
|
||||
getLocationsForBook(bookName) {
|
||||
const bookLocations = {
|
||||
"Genesis": ["babylon", "egypt_memphis"],
|
||||
"Exodus": ["egypt_memphis", "mount_sinai"],
|
||||
"Joshua": ["jericho", "jordan_river"],
|
||||
"1 Samuel": ["bethlehem"],
|
||||
"2 Samuel": ["jerusalem"],
|
||||
"1 Kings": ["jerusalem", "mount_carmel"],
|
||||
"Psalms": ["jerusalem"],
|
||||
"Matthew": ["bethlehem", "nazareth", "capernaum", "jerusalem"],
|
||||
"Mark": ["capernaum", "sea_of_galilee", "jerusalem"],
|
||||
"Luke": ["nazareth", "bethlehem", "jericho", "jerusalem"],
|
||||
"John": ["capernaum", "sea_of_galilee", "jerusalem"],
|
||||
"Acts": ["jerusalem", "damascus", "antioch", "athens", "corinth", "ephesus", "rome"],
|
||||
"Romans": ["rome"],
|
||||
"1 Corinthians": ["corinth"],
|
||||
"Ephesians": ["ephesus"],
|
||||
"Revelation": ["ephesus"]
|
||||
};
|
||||
|
||||
return bookLocations[bookName] || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight a specific location
|
||||
*/
|
||||
highlightLocation(location) {
|
||||
// This would add visual highlighting - implementation depends on specific needs
|
||||
console.log(`Highlighting ${location.name}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all highlights
|
||||
*/
|
||||
clearHighlights() {
|
||||
// Clear any existing highlights
|
||||
console.log("Clearing highlights");
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize map (useful when container size changes)
|
||||
*/
|
||||
resize() {
|
||||
if (this.map) {
|
||||
this.map.invalidateSize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the map instance
|
||||
*/
|
||||
destroy() {
|
||||
if (this.map) {
|
||||
this.map.remove();
|
||||
this.map = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Make BiblicalMaps available globally
|
||||
window.BiblicalMaps = BiblicalMaps;
|
||||
|
||||
// Auto-initialize if map container exists
|
||||
const mapContainer = document.getElementById('biblical-map');
|
||||
if (mapContainer) {
|
||||
window.biblicalMapsInstance = new BiblicalMaps();
|
||||
window.biblicalMapsInstance.init('biblical-map');
|
||||
}
|
||||
});
|
||||
|
||||
// CSS styles for map components
|
||||
const mapStyles = `
|
||||
<style>
|
||||
.biblical-location-popup .leaflet-popup-content {
|
||||
font-family: Georgia, serif;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.biblical-location-info h3 {
|
||||
margin: 0 0 8px 0;
|
||||
color: #8B4513;
|
||||
font-size: 16px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.biblical-location-info .description {
|
||||
margin: 8px 0;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.biblical-location-info .verses {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.biblical-location-info .verse-link {
|
||||
color: #8B4513;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.biblical-location-info .verse-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.biblical-location-marker {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.leaflet-control-layers {
|
||||
font-family: Georgia, serif;
|
||||
}
|
||||
|
||||
#biblical-map {
|
||||
height: 500px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.map-search {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.map-search input {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-family: Georgia, serif;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.map-search button {
|
||||
padding: 8px 16px;
|
||||
background: #8B4513;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.map-search button:hover {
|
||||
background: #A0522D;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
|
||||
// Inject styles into document head
|
||||
if (typeof document !== 'undefined') {
|
||||
document.head.insertAdjacentHTML('beforeend', mapStyles);
|
||||
}
|
||||
@@ -0,0 +1,490 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Biblical Maps - KJV Study</title>
|
||||
|
||||
<!-- Leaflet CSS -->
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||||
crossorigin=""/>
|
||||
|
||||
<link rel="stylesheet" href="{{ url_for('static', path='/style.css') }}">
|
||||
|
||||
<style>
|
||||
.maps-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.maps-header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.maps-header h1 {
|
||||
color: #8B4513;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.maps-header p {
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.map-controls {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.control-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.control-group:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.control-group label {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
color: #8B4513;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-family: Georgia, serif;
|
||||
min-width: 200px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search-btn, .book-btn {
|
||||
padding: 10px 16px;
|
||||
background: #8B4513;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-family: Georgia, serif;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.search-btn:hover, .book-btn:hover {
|
||||
background: #A0522D;
|
||||
}
|
||||
|
||||
.book-selector {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.book-btn {
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
background: #6c757d;
|
||||
}
|
||||
|
||||
.book-btn.active {
|
||||
background: #8B4513;
|
||||
}
|
||||
|
||||
.period-filter {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.period-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.period-checkbox input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#biblical-map {
|
||||
height: 600px;
|
||||
border: 2px solid #8B4513;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.map-legend {
|
||||
background: white;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.map-legend h3 {
|
||||
margin: 0 0 10px 0;
|
||||
color: #8B4513;
|
||||
}
|
||||
|
||||
.legend-items {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.legend-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 2px solid white;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid #f5c6cb;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-panel {
|
||||
background: #e7f3ff;
|
||||
border: 1px solid #b8daff;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.info-panel h3 {
|
||||
color: #004085;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.info-panel p {
|
||||
margin: 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.maps-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#biblical-map {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
.book-selector {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.legend-items {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<nav class="navbar">
|
||||
<div class="nav-brand">
|
||||
<a href="/">📖 KJV Study</a>
|
||||
</div>
|
||||
<div class="nav-links">
|
||||
<a href="/">Home</a>
|
||||
<a href="/search">Search</a>
|
||||
<a href="/study-guides">Study Guides</a>
|
||||
<a href="/verse-of-the-day">Verse of the Day</a>
|
||||
<a href="/biblical-maps" class="active">Biblical Maps</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="maps-container">
|
||||
<div class="maps-header">
|
||||
<h1>🗺️ Biblical Maps</h1>
|
||||
<p>Explore the geographical context of Scripture with interactive maps showing biblical locations, journeys, and historical events from both the Old and New Testaments.</p>
|
||||
</div>
|
||||
|
||||
<div class="info-panel">
|
||||
<h3>📍 How to Use Biblical Maps</h3>
|
||||
<p>Click on map markers to learn about biblical locations and their significance. Use the layer controls to show different time periods, search for specific places, or filter by Bible books. Each location includes relevant Scripture references you can click to explore further.</p>
|
||||
</div>
|
||||
|
||||
<div class="map-controls">
|
||||
<div class="control-group">
|
||||
<label for="location-search">🔍 Search Biblical Locations</label>
|
||||
<div class="search-container">
|
||||
<input type="text"
|
||||
id="location-search"
|
||||
class="search-input"
|
||||
placeholder="Search for Jerusalem, Bethlehem, Damascus..."
|
||||
autocomplete="off">
|
||||
<button type="button" id="search-location-btn" class="search-btn">
|
||||
Search
|
||||
</button>
|
||||
<button type="button" id="clear-search-btn" class="search-btn" style="background: #6c757d;">
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
<div id="search-error" class="error-message">
|
||||
Location not found. Try searching for Jerusalem, Bethlehem, Damascus, or other biblical cities.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label>📚 Filter by Bible Book</label>
|
||||
<div class="book-selector">
|
||||
<button type="button" class="book-btn" data-book="Genesis">Genesis</button>
|
||||
<button type="button" class="book-btn" data-book="Exodus">Exodus</button>
|
||||
<button type="button" class="book-btn" data-book="Joshua">Joshua</button>
|
||||
<button type="button" class="book-btn" data-book="1 Samuel">1 Samuel</button>
|
||||
<button type="button" class="book-btn" data-book="2 Samuel">2 Samuel</button>
|
||||
<button type="button" class="book-btn" data-book="1 Kings">1 Kings</button>
|
||||
<button type="button" class="book-btn" data-book="Matthew">Matthew</button>
|
||||
<button type="button" class="book-btn" data-book="Mark">Mark</button>
|
||||
<button type="button" class="book-btn" data-book="Luke">Luke</button>
|
||||
<button type="button" class="book-btn" data-book="John">John</button>
|
||||
<button type="button" class="book-btn" data-book="Acts">Acts</button>
|
||||
<button type="button" class="book-btn" data-book="Romans">Romans</button>
|
||||
<button type="button" class="book-btn clear-filter">Clear Filter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label>⏰ Time Periods</label>
|
||||
<div class="period-filter">
|
||||
<div class="period-checkbox">
|
||||
<input type="checkbox" id="show-ot" checked>
|
||||
<label for="show-ot">Old Testament</label>
|
||||
</div>
|
||||
<div class="period-checkbox">
|
||||
<input type="checkbox" id="show-nt" checked>
|
||||
<label for="show-nt">New Testament</label>
|
||||
</div>
|
||||
<div class="period-checkbox">
|
||||
<input type="checkbox" id="show-journeys" checked>
|
||||
<label for="show-journeys">Paul's Journeys</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="biblical-map"></div>
|
||||
|
||||
<div class="map-legend">
|
||||
<h3>🗺️ Map Legend</h3>
|
||||
<div class="legend-items">
|
||||
<div class="legend-item">
|
||||
<div class="legend-icon" style="background-color: #8B4513;">🏛️</div>
|
||||
<span>Biblical Cities</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-icon" style="background-color: #8B7355;">⛰️</div>
|
||||
<span>Mountains & High Places</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-icon" style="background-color: #4682B4;">🌊</div>
|
||||
<span>Bodies of Water</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-icon" style="background-color: #DAA520;">🕌</div>
|
||||
<span>Temples & Holy Sites</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-icon" style="background-color: #DC143C;">✨</div>
|
||||
<span>Major Biblical Events</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Leaflet JavaScript -->
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
|
||||
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
|
||||
crossorigin=""></script>
|
||||
|
||||
<!-- Biblical Maps JavaScript -->
|
||||
<script src="{{ url_for('static', path='/js/biblical-maps.js') }}"></script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize the biblical maps
|
||||
const biblicalMaps = new BiblicalMaps();
|
||||
biblicalMaps.init('biblical-map');
|
||||
|
||||
// Search functionality
|
||||
const searchInput = document.getElementById('location-search');
|
||||
const searchBtn = document.getElementById('search-location-btn');
|
||||
const clearBtn = document.getElementById('clear-search-btn');
|
||||
const errorMsg = document.getElementById('search-error');
|
||||
|
||||
function performSearch() {
|
||||
const query = searchInput.value.trim();
|
||||
if (query) {
|
||||
const found = biblicalMaps.searchLocation(query);
|
||||
if (!found) {
|
||||
errorMsg.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
errorMsg.style.display = 'none';
|
||||
}, 3000);
|
||||
} else {
|
||||
errorMsg.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
searchBtn.addEventListener('click', performSearch);
|
||||
searchInput.addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
performSearch();
|
||||
}
|
||||
});
|
||||
|
||||
clearBtn.addEventListener('click', function() {
|
||||
searchInput.value = '';
|
||||
errorMsg.style.display = 'none';
|
||||
// Reset map to default view
|
||||
biblicalMaps.map.setView([31.7683, 35.2137], 7);
|
||||
});
|
||||
|
||||
// Book filter functionality
|
||||
const bookButtons = document.querySelectorAll('.book-btn');
|
||||
bookButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const book = this.dataset.book;
|
||||
|
||||
if (this.classList.contains('clear-filter')) {
|
||||
// Clear all filters
|
||||
bookButtons.forEach(btn => btn.classList.remove('active'));
|
||||
biblicalMaps.clearHighlights();
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle active state
|
||||
bookButtons.forEach(btn => btn.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
|
||||
// Show locations for this book
|
||||
biblicalMaps.showBookLocations(book);
|
||||
});
|
||||
});
|
||||
|
||||
// Period filter functionality
|
||||
const otCheckbox = document.getElementById('show-ot');
|
||||
const ntCheckbox = document.getElementById('show-nt');
|
||||
const journeysCheckbox = document.getElementById('show-journeys');
|
||||
|
||||
function updateLayerVisibility() {
|
||||
const map = biblicalMaps.map;
|
||||
|
||||
// Old Testament layers
|
||||
if (otCheckbox.checked) {
|
||||
if (!map.hasLayer(biblicalMaps.mapLayers['Old Testament Cities'])) {
|
||||
map.addLayer(biblicalMaps.mapLayers['Old Testament Cities']);
|
||||
}
|
||||
} else {
|
||||
if (map.hasLayer(biblicalMaps.mapLayers['Old Testament Cities'])) {
|
||||
map.removeLayer(biblicalMaps.mapLayers['Old Testament Cities']);
|
||||
}
|
||||
}
|
||||
|
||||
// New Testament layers
|
||||
if (ntCheckbox.checked) {
|
||||
if (!map.hasLayer(biblicalMaps.mapLayers['New Testament Cities'])) {
|
||||
map.addLayer(biblicalMaps.mapLayers['New Testament Cities']);
|
||||
}
|
||||
} else {
|
||||
if (map.hasLayer(biblicalMaps.mapLayers['New Testament Cities'])) {
|
||||
map.removeLayer(biblicalMaps.mapLayers['New Testament Cities']);
|
||||
}
|
||||
}
|
||||
|
||||
// Paul's Journeys layers
|
||||
if (journeysCheckbox.checked) {
|
||||
if (!map.hasLayer(biblicalMaps.mapLayers["Paul's Journeys"])) {
|
||||
map.addLayer(biblicalMaps.mapLayers["Paul's Journeys"]);
|
||||
}
|
||||
} else {
|
||||
if (map.hasLayer(biblicalMaps.mapLayers["Paul's Journeys"])) {
|
||||
map.removeLayer(biblicalMaps.mapLayers["Paul's Journeys"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Always show major events and tribal territories
|
||||
if (!map.hasLayer(biblicalMaps.mapLayers['Major Events'])) {
|
||||
map.addLayer(biblicalMaps.mapLayers['Major Events']);
|
||||
}
|
||||
if (!map.hasLayer(biblicalMaps.mapLayers['Tribal Territories'])) {
|
||||
map.addLayer(biblicalMaps.mapLayers['Tribal Territories']);
|
||||
}
|
||||
}
|
||||
|
||||
otCheckbox.addEventListener('change', updateLayerVisibility);
|
||||
ntCheckbox.addEventListener('change', updateLayerVisibility);
|
||||
journeysCheckbox.addEventListener('change', updateLayerVisibility);
|
||||
|
||||
// Auto-complete suggestions for search
|
||||
const biblicalLocationNames = [
|
||||
'Jerusalem', 'Bethlehem', 'Nazareth', 'Capernaum', 'Jericho',
|
||||
'Damascus', 'Babylon', 'Memphis', 'Mount Sinai', 'Mount Carmel',
|
||||
'Antioch', 'Athens', 'Corinth', 'Ephesus', 'Rome',
|
||||
'Sea of Galilee', 'Dead Sea', 'Jordan River'
|
||||
];
|
||||
|
||||
searchInput.addEventListener('input', function() {
|
||||
// Simple auto-complete logic could be added here
|
||||
const value = this.value.toLowerCase();
|
||||
// For now, just hide error when user starts typing
|
||||
errorMsg.style.display = 'none';
|
||||
});
|
||||
|
||||
// Responsive map resize
|
||||
window.addEventListener('resize', function() {
|
||||
biblicalMaps.resize();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user