Search code examples
javascripthtmlwordpresswebgeolocation

Use Geolocation Show Nearest Location to Web Visitor using JavaScript (COMBINING SCRIPTS)


I'm currently in the process of redoing my company's website. It would be really cool to, as soon as someone loads any page of our new site, display the location that is either closest to them, or within the business' service radius (±20mi) in the top bar beside a location pinpoint icon. I've been searching for a few days now about how to find a way to make this possible, and JavaScript seems to be the only way to accomplish this. I'm new to JS, so I'm not sure of the best way to accomplish it.

I need to combine the following scripts that work flawlessly individually, but not together at the moment.

////// SCRIPT 1 /////////
function geoFindMe() {

  const status = document.querySelector('#status');
  const mapLink = document.querySelector('#map-link');

  mapLink.href = '';
  mapLink.textContent = '';

  function success(position) {
    const latitude  = position.coords.latitude;
    const longitude = position.coords.longitude;

    status.textContent = '';
    mapLink.href = `https://www.openstreetmap.org/#map=18/${latitude}/${longitude}`;
    mapLink.textContent = `Latitude: ${latitude} °, Longitude: ${longitude} °`;
  }

  function error() {
    status.textContent = 'Unable to retrieve your location';
  }

  if (!navigator.geolocation) {
    status.textContent = 'Geolocation is not supported by your browser';
  } else {
    status.textContent = 'Locating…';
    navigator.geolocation.getCurrentPosition(success, error);
  }

}

document.querySelector('#find-me').addEventListener('click', geoFindMe);


//////////// SCRIPT 2 ////////////

function distance(lat1, lon1, lat2, lon2, unit) {
    	var radlat1 = Math.PI * lat1/180
    	var radlat2 = Math.PI * lat2/180
    	var theta = lon1-lon2
    	var radtheta = Math.PI * theta/180
    	var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
    	if (dist > 1) {
    		dist = 1;
    	}
    	dist = Math.acos(dist)
    	dist = dist * 180/Math.PI
    	dist = dist * 60 * 1.1515
    	if (unit=="K") { dist = dist * 1.609344 }
    	if (unit=="N") { dist = dist * 0.8684 }
    	return dist
    }

    var data = [{
        "lat": "36.5983825",
        "lng": "-82.1828577",
        "location": "Bristol"
    }, {
        "lat": "36.7053664",
        "lng": "-81.999551",
        "location": "Abingdon"
    }, {
        "lat": "35.9120595",
        "lng": "-84.0979276",
        "location": "West Knoxville"
    }, {
        "lat": "35.8718708",
        "lng": "-83.5642387",
        "location": "Sevierville"
    }];

    var html = "";
    var poslat = 36.5983825;
    var poslng = -82.1828577;
    
    for (var i = 0; i < data.length; i++) {
        // if this location is within 0.1KM of the user, add it to the list
        if (distance(poslat, poslng, data[i].lat, data[i].lng, "M") <= 20) {
            html += '<a href="/' + data[i].location + '" target="_blank"><i class="icon-location"></i>' + data[i].location + '</a> ';
        }
    }
    
    $('#nearestLocation').append(html);
///// SCRIPT 1 //////<br><br>

<button id = "find-me">Show my location</button><br/>
<p id = "status"></p>
<a id = "map-link" target="_blank"></a>

///// SCRIPT 2 //////<br><br>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="nearestLocation"></div>
<br>
<br>

Script 1 gets the users' current location upon request, and Script 2 compares a given lat/long against the rest to find the closest set(s) within a 20 mile radius.

We have 14 locations in the U.S. only, and this is why we need to use GeoLocation as opposed to GeoIP. GeoIP is not accurate enough for us.

postlat and postlng are what Script 2 uses to compare against the given lat/lng coordinates, and Script 1 can provide these, I just can't get them to work together towards the same common goal.

Thanks!


Solution

  • Attached is the solution I was looking for in the event anyone else is in the same predicament. Keep in mind, this will only function if you have a valid SSL certificate on your HTML 5 website.

    var lat = 0;
    var lng = 0;
    function geoFindMe() {
    
      const status = document.querySelector('#status');
      const mapLink = document.querySelector('#map-link');
    
      mapLink.href = '';
      mapLink.textContent = '';
    
      function success(position) {
        const latitude  = position.coords.latitude;
        const longitude = position.coords.longitude;
    
        status.textContent = '';
        mapLink.href = ``;
        mapLink.textContent = ``;
        lat = position.coords.latitude;
        lng = position.coords.longitude;
        showNearestLocations();
      }
    
      function error() {
        status.textContent = 'Unable to retrieve your location';
      }
    
      if (!navigator.geolocation) {
        status.textContent = 'Geolocation is not supported by your browser';
      } else {
        status.textContent = 'Locating…';
        navigator.geolocation.getCurrentPosition(success, error);
      }
    
    }
    
    document.querySelector('#find-me').addEventListener('click', geoFindMe);
    
    
    function distance(lat1, lon1, lat2, lon2, unit) {
        	var radlat1 = Math.PI * lat1/180
        	var radlat2 = Math.PI * lat2/180
        	var theta = lon1-lon2
        	var radtheta = Math.PI * theta/180
        	var dist = Math.sin(radlat1) *
    Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        	if (dist > 1) {
        		dist = 1;
        	}
        	dist = Math.acos(dist)
        	dist = dist * 180/Math.PI
        	dist = dist * 60 * 1.1515
        	if (unit=="K") { dist = dist * 1.609344 }
        	if (unit=="N") { dist = dist * 0.8684 }
        	return dist
        }
    
    function showNearestLocations() {
        var data = [{
            "lat": 36.5983825,
            "lng": -82.1828577,
            "location": "Bristol",
            "link": "bristol",
        }, {
            "lat": 36.7053664,
            "lng": -81.999551,
            "location": "Abingdon",
            "link": "abingdon",
        }, {
            "lat": 35.9120595,
            "lng": -84.0979276,
            "location": "West Knoxville",
            "link": "west-knoxville",
        }, {
            "lat": 35.8718708,
            "lng": -83.5642387,
            "location": "Sevierville",
            "link": "sevierville",
        }];
    
        var html = "";
        var poslat = lat;
        var poslng = lng;
        
        var found = false;
        for (var i = 0; i < data.length; i++) {
            // if this location is within 0.1KM of the user, add it to the list
            if (distance(poslat, poslng, data[i].lat, data[i].lng, "M") <= 20) {
                html += '<a href="/' + data[i].link + '" target="_blank"><i class="icon-location"></i>' + data[i].location + '</a> ';
              found = true;
            }
        }
        
        $('#nearestLocation').html(html);
        if (!found) {
          $('#nearestLocation').html("no near location found");
        }
    }
    #map-link {
      display: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <button id = "find-me">Show my nearest locations</button> <span id="nearestLocation"></span><p id = "status"></p>
    <a id = "map-link" target="_blank"></a>