Siteβ―Builder
Editing:
index.php
writable 0666
<?php $geo_json_dir = __DIR__ . '/json-data'; $bounds_file = $geo_json_dir . '/states-bounds.json'; $bounds_data = file_exists($bounds_file) ? json_decode(file_get_contents($bounds_file), true) : []; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Find the Closest City in the USA | BestDealOn Geo Directory</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/bestdealon.svg" type="image/svg+xml"> <meta name="description" content="Instantly locate the nearest US city to you and browse every city in every state. Ultra-fast location search for travel, deals, or finding your local BestDealOn partner!"> <link rel="canonical" href="https://www.bestdealon.com/geo/"> <meta property="og:title" content="BestDealOn - Find Your Closest City in the USA"> <meta property="og:description" content="Find your nearest US city fast, browse by state, or use your phone's location. Perfect for deals, local businesses, and travel."> <meta property="og:type" content="website"> <meta property="og:url" content="https://www.bestdealon.com/geo/"> <meta property="og:site_name" content="BestDealOn Geo Directory"> <meta name="robots" content="index, follow"> <style> body { background: #f7fafc; font-family: 'Segoe UI', Arial, sans-serif; color: #2e3a4c; margin: 0; min-height: 100vh; } .card { background: #fff; max-width: 520px; margin: 3rem auto 2rem auto; padding: 2.2rem 2rem 1.5rem 2rem; border-radius: 18px; box-shadow: 0 2px 14px 0 rgba(48,65,105,.09), 0 0.5px 2px 0 rgba(50,50,50,0.03); text-align: center; } .card-title { font-size: 2.1rem; font-weight: 800; color: #31548a; letter-spacing: 1px; margin-bottom: 0.2rem; } .card-slogan { font-size: 1.11rem; color: #568ad6; margin-bottom: 1.2rem; font-weight: 500; } .geo-ui { max-width: 520px; margin: 0 auto; background: #fff; border-radius: 13px; box-shadow: 0 1.5px 8px 0 rgba(70,100,140,0.10); padding: 1.2rem 1.3rem 2rem 1.3rem; } select, button { padding: 0.3em 1em; font-size: 1rem; border-radius: 8px; border: 1px solid #d0dae8; background: #f6fafd; color: #2e3a4c; margin-bottom: 1rem; } select:focus, button:focus { outline: 2px solid #6ab1ff; } #city-list ul { list-style: none; padding-left: 0.2em; margin: 0; } #city-list li { line-height: 1.9; font-size: 1.12em; text-align: left; margin-left: 0.2em; margin-bottom: 0.07em; } #city-list a { text-decoration: none; color: #3972c6; font-weight: 600; padding-left: 0.10em; } #city-list a:hover { text-decoration: underline;} #nearest-city { margin: 1em 0; font-size: 1.15em; color: #23486b; } #nearby-cities { margin: 0.6em 0 1em 0; color: #6b7892; } @media (max-width: 600px) { .card, .geo-ui { max-width: 97vw; padding: 1rem; } #city-list li { font-size: 1.03em; } } </style> </head> <body> <div class="card"> <div class="card-title">BestDealOn</div> <div class="card-slogan">Find the Closest City Fast!</div> <button id="locate-btn" style="margin-bottom:1em;">π Locate Me</button> <div> <label for="state-select"><b>State:</b></label> <select id="state-select"> <option value="">β Select a State β</option> <?php foreach($bounds_data as $b): ?> <option value="<?php echo htmlspecialchars($b['state']); ?>"><?php echo htmlspecialchars($b['name']); ?></option> <?php endforeach; ?> </select> </div> <div id="city-ui"></div> </div> <script> function capitalizeFirstSlug(str) { return str.replace(/\/([^\/]+)\/?$/, function(match, slug) { if (!slug.length) return match; return '/' + slug.charAt(0).toUpperCase() + slug.slice(1) + '/'; }); } // Utility: load JSON file function loadJSON(url, cb) { fetch(url).then(resp => resp.json()).then(cb); } let stateBounds = <?php echo json_encode($bounds_data); ?>; // On "Locate Me" document.getElementById('locate-btn').onclick = function() { if (!stateBounds) return alert('State bounds file not found.'); if (!navigator.geolocation) { alert("Geolocation is not supported by your browser."); return; } navigator.geolocation.getCurrentPosition(function(pos) { var lat = pos.coords.latitude, lon = pos.coords.longitude; let found = stateBounds.find(st => lat >= st.minLat && lat <= st.maxLat && lon >= st.minLon && lon <= st.maxLon ); if (found) { let sel = document.getElementById('state-select'); for (var i=0; i<sel.options.length; i++) if (sel.options[i].value === found.state) sel.selectedIndex = i; sel.dispatchEvent(new Event('change')); setTimeout(function() { findNearestCity(found.state, lat, lon); }, 350); } else { alert('Could not detect your state from your location.'); } }, function(err){ alert("Location failed: " + err.message); }); }; // On State Select: load and show cities document.getElementById('state-select').addEventListener('change', function() { var state = this.value; var cityUI = document.getElementById('city-ui'); if (!state) { cityUI.innerHTML = ''; return; } cityUI.innerHTML = '<em>Loading cities...</em>'; loadJSON('json-data/' + state + '.json', function(cities) { let groups = {}; cities.forEach(c => { let letter = c.city[0].toUpperCase(); if (!groups[letter]) groups[letter] = []; groups[letter].push(c); }); let html = '<div id="nearest-city"></div><div id="nearby-cities"></div><div id="city-list">'; Object.keys(groups).sort().forEach(letter => { html += '<div style="font-size:1.09em;font-weight:700;margin-top:1em;">' + letter + '</div><ul>'; groups[letter].sort((a,b) => a.city.localeCompare(b.city)).forEach(c => { html += `<li><a href="${capitalizeFirstSlug(c.url)}">${c.city}</a> <span style="color:#b8c6de;font-size:0.98em;">(${c.lat},${c.lon})</span></li>`; }); html += '</ul>'; }); html += '</div>'; cityUI.innerHTML = html; }); }); // Find and highlight nearest city and nearby cities function findNearestCity(state, userLat, userLon) { loadJSON('json-data/' + state + '.json', function(cities) { let minDist = 999999, nearest = null; let dists = []; for (let i = 0; i < cities.length; i++) { let c = cities[i]; let d = Math.sqrt( Math.pow(userLat - c.lat, 2) + Math.pow(userLon - c.lon, 2) ); dists.push({city: c, dist: d}); if (d < minDist) { minDist = d; nearest = c; } } dists.sort((a, b) => a.dist - b.dist); let cityDiv = document.getElementById('nearest-city'); let nearbyDiv = document.getElementById('nearby-cities'); if (nearest) { let nearbyHtml = ""; let nearby = dists.slice(1, 5); if (nearby.length) { nearbyHtml = `Nearby cities: `; nearbyHtml += nearby.map(nb => `<a href="${capitalizeFirstSlug(nb.city.url)}" style="font-size:1em;margin:0 0.7em 0 0">${nb.city.city}</a>` ).join(''); } cityDiv.innerHTML = `Closest city: <b><a href="${capitalizeFirstSlug(nearest.url)}">${nearest.city}</a></b> <span style="color:#b8c6de;font-size:0.98em;">(${nearest.lat},${nearest.lon})</span>`; nearbyDiv.innerHTML = nearbyHtml; } else { cityDiv.innerHTML = ''; nearbyDiv.innerHTML = ''; } }); } </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel