From bf5a0876b6db7084e1c5319b66fc29c2f28744b5 Mon Sep 17 00:00:00 2001 From: Eivind Date: Fri, 28 Nov 2025 00:05:31 +0100 Subject: [PATCH] feat: Add geocoding functionality and implement pan/zoom for the family tree view. --- index.html | 5 ++- script.js | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ style.css | 21 ++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 7372f09..6a90f53 100644 --- a/index.html +++ b/index.html @@ -116,7 +116,10 @@
- +
+ + +
diff --git a/script.js b/script.js index 21a7bd4..49be7a6 100644 --- a/script.js +++ b/script.js @@ -196,6 +196,25 @@ memberForm.addEventListener('submit', (e) => { } }); +// Geocoding +document.getElementById('geocodeBtn').addEventListener('click', () => { + const location = document.getElementById('location').value; + if (!location) return; + + const geocoder = new google.maps.Geocoder(); + geocoder.geocode({ 'address': location }, (results, status) => { + if (status === 'OK') { + const lat = results[0].geometry.location.lat(); + const lng = results[0].geometry.location.lng(); + + document.getElementById('lat').value = lat.toFixed(6); + document.getElementById('lng').value = lng.toFixed(6); + } else { + alert('Kunne ikke finne koordinater for dette stedet: ' + status); + } + }); +}); + // --- Feature: Family Tree --- function renderTree() { @@ -490,3 +509,78 @@ function renderHistory() { list.appendChild(item); }); } + +// --- Feature: Family Tree Navigation (Pan/Zoom) --- + +let treeState = { + scale: 1, + panning: false, + pointX: 0, + pointY: 0, + startX: 0, + startY: 0 +}; + +function setupPanZoom() { + const treeTab = document.getElementById('tree-tab'); + const treeContainer = document.getElementById('tree-container'); + + // Zoom (Wheel) + treeTab.addEventListener('wheel', (e) => { + e.preventDefault(); + + const xs = (e.clientX - treeState.pointX) / treeState.scale; + const ys = (e.clientY - treeState.pointY) / treeState.scale; + + const delta = -e.deltaY; + (delta > 0) ? (treeState.scale *= 1.1) : (treeState.scale /= 1.1); + + // Limit zoom + treeState.scale = Math.min(Math.max(0.1, treeState.scale), 5); + + treeState.pointX = e.clientX - xs * treeState.scale; + treeState.pointY = e.clientY - ys * treeState.scale; + + setTransform(); + }); + + // Pan (Mouse) + treeTab.addEventListener('mousedown', (e) => { + if (e.target.closest('.family-card') || e.target.closest('.fab')) return; // Don't drag if clicking card/button + + e.preventDefault(); + treeState.startX = e.clientX - treeState.pointX; + treeState.startY = e.clientY - treeState.pointY; + treeState.panning = true; + }); + + treeTab.addEventListener('mousemove', (e) => { + if (!treeState.panning) return; + e.preventDefault(); + treeState.pointX = e.clientX - treeState.startX; + treeState.pointY = e.clientY - treeState.startY; + setTransform(); + }); + + treeTab.addEventListener('mouseup', () => { + treeState.panning = false; + }); + + treeTab.addEventListener('mouseleave', () => { + treeState.panning = false; + }); + + function setTransform() { + treeContainer.style.transform = `translate(${treeState.pointX}px, ${treeState.pointY}px) scale(${treeState.scale})`; + } + + // Initial center (approx) + treeState.pointX = (window.innerWidth - 1000) / 2; // Assuming 1000px content width + treeState.pointY = 50; + setTransform(); +} + +// Initialize PanZoom when DOM is ready +document.addEventListener('DOMContentLoaded', () => { + setupPanZoom(); +}); diff --git a/style.css b/style.css index 0bd033d..27ad68b 100644 --- a/style.css +++ b/style.css @@ -376,4 +376,25 @@ textarea:focus { input[type="radio"] { width: auto; margin: 0; +} + +/* Pan and Zoom Styles */ +#tree-tab { + overflow: hidden; /* Hide scrollbars, we use custom pan */ + position: relative; + cursor: grab; +} + +#tree-tab:active { + cursor: grabbing; +} + +#tree-container { + transform-origin: 0 0; /* Zoom from top-left */ + position: absolute; + top: 0; + left: 0; + /* Ensure it has size */ + min-width: 100%; + min-height: 100%; } \ No newline at end of file