1

I want to make a div appear based on distance. For this I'm getting the location of the user and the coordinates of the place the div is supposed to appear and I'm being successful making this happen. My problem now, is that there's gonna be different places where I want this to be available, so I need to find a way to loop and constantly be checking where the person is and see if its close to the distance of my coordinates.

-- Getting Location of person

if (navigator.geolocation){
    navigator.geolocation.watchPosition(showPosition)
}

-- Function to work div appearing

function showPosition(position){

  let locationLatitude = []
  let locationsLongitude = []

  //AJAX CALL TO GET THE POSITION OF THE PLACES AND PUSHING THEM TO THE ARRAYS
  let success = function(res){
    let locations = res.locations

    for (var i=0; i<locations.length; i++){
      locationLatitude.push(locations[i]['place_latitude'])
      locationsLongitude.push(locations[i]['place_longitude'])
    }
  }

   $.ajax({
      type: 'GET',
      url: '/api/locations',
      crossDomain: true,
      dataType: 'json',
      async: false,
      success : success,
  });

  // LOOP TO GET ALL COORDIANTES FROM PLACES (LAT,LONG)
  var locationLatitudeLength = locationLatitude.length
  var locationsLongitudeLength = locationsLongitude.length
  let startPosLat
  let startPosLong

  for(var i=0; i<locationLatitudeLength; i++){

    for(var j=0; j<locationsLongitudeLength; j++){
      startPosLat = locationLatitude[i]
      startPosLong = locationsLongitude[j]

      userlocationLatitude = position.coords.latitude
      userlocationLongitude = position.coords.longitude

     //PASS VALUES OF COORDINATES TO THE FUNCTION
     let distance = calculateDistance(startPosLat, startPosLong, userlocationLatitude, userlocationLongitude)

      }

  }

   if(distance < .05){
      $('.div-image').attr('src', 'pic2.jpg')
   }else if(distance > .05){
      $('.div-image').attr('src', 'pic.jpg')
   }


    //function to calculate the distance between two points of coordinates 
    function calculateDistance(lat1, lon1, lat2, lon2) {
        var R = 6371; // km
        var dLat = (lat2-lat1).toRad();
        var dLon = (lon2-lon1).toRad();
        var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
                Math.sin(dLon/2) * Math.sin(dLon/2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        var d = R * c;
        return d;
    }
      Number.prototype.toRad = function() {
        return this * Math.PI / 180;
    }
}

the problem with this is that it doesn't recognize the coordinates coming from the loop.

Anyone has a recommendation on how to make the function run for each coordinate on the loop to check if I'm there or not.

3 Answers 3

3

It appears that the double loop going through the coordinates does not wait for the response from the ajax (I'm assuming that all of the coordinates are required before processing). Since the ajax call is asynchronous, the locations won't be populated until the server responds; however, the loop going through the locations array will start executing immediately after the initial request is made to the server and, most importantly, before the locations are populated.

Try moving a majority of your function into the success function.

function showPosition(position){

  let locationLatitude = []
  let locationsLongitude = []

  //AJAX CALL TO GET THE POSITION OF THE PLACES AND PUSHING THEM TO THE ARRAYS
  let success = function(res){
    let locations = res.locations

    for (var i=0; i<locations.length; i++){
      locationLatitude.push(locations[i]['place_latitude'])
      locationsLongitude.push(locations[i]['place_longitude'])
    }

    // LOOP TO GET ALL COORDIANTES FROM PLACES (LAT,LONG)
    var locationLatitudeLength = locationLatitude.length
    var locationsLongitudeLength = locationsLongitude.length
    let startPosLat
    let startPosLong

    for(var i=0; i<locationLatitudeLength; i++){

      for(var j=0; j<locationsLongitudeLength; j++){
        startPosLat = locationLatitude[i]
        startPosLong = locationsLongitude[j]

        userlocationLatitude = position.coords.latitude
        userlocationLongitude = position.coords.longitude

        //PASS VALUES OF COORDINATES TO THE FUNCTION
        let distance = calculateDistance(startPosLat, startPosLong, userlocationLatitude, userlocationLongitude)
      }
    }

    if(distance < .05){
        $('.div-image').attr('src', 'pic2.jpg')
    }else if(distance > .05){
        $('.div-image').attr('src', 'pic.jpg')
    }
  }

   $.ajax({
      type: 'GET',
      url: '/api/locations',
      crossDomain: true,
      dataType: 'json',
      async: false,
      success : success,
  });

  //function to calculate the distance between two points of coordinates 
  function calculateDistance(lat1, lon1, lat2, lon2) {
      var R = 6371; // km
      var dLat = (lat2-lat1).toRad();
      var dLon = (lon2-lon1).toRad();
      var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
              Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
              Math.sin(dLon/2) * Math.sin(dLon/2);
      var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
      var d = R * c;
      return d;
  }

  Number.prototype.toRad = function() {
    return this * Math.PI / 180;
  }
}```
Sign up to request clarification or add additional context in comments.

Comments

1

I think your algorithm could be simplified quite a bit. In particular, breaking the latitudes and longitudes into separate arrays and then later using nested for loops to reunite them seems unnecessary. Here's a suggestion that skips those steps.

Note that this is totally untested, but it might get you well along the right track.

Other things to note are the possibility of using for...of instead of traditional for loops, using distance in the same scope in which it gets declared, and being ready for the situation where distance == .05.

function showPosition(position){
  const userlocationLatitude = position.coords.latitude;
  const userlocationLongitude = position.coords.longitude;
  let success = function(res){
    for(let location of res.locations){
      let startPosLat = location['place_latitude'],
          startPosLng = location['place_longitude'],
          distance = calculateDistance(startPosLat, startPosLong, userlocationLatitude, userlocationLongitude);
      if(distance < .05){ $('.div-image').attr('src', 'pic2.jpg'); }
      else{ $('.div-image').attr('src', 'pic.jpg'); }  
    }
  }
  $.ajax({ type: 'GET', url: '/api/locations', crossDomain: true, dataType: 'json', async: false, success : success });

  //function to calculate the distance between two points of coordinates 
  function calculateDistance(lat1, lon1, lat2, lon2) {
      var R = 6371, dLat = (lat2-lat1).toRad(), dLon = (lon2-lon1).toRad(),
          a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * Math.sin(dLon/2) * Math.sin(dLon/2),
          c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
      return R * c;
  }
  Number.prototype.toRad = function() { return this * Math.PI / 180; }
}

1 Comment

Thank you so much, this helped and now my function is running with all the coordinates!! :)
1

I would first suggest using an array of arrays to store coordinates so your latitude and longitude are referenced near eachother. I have given some basic examples of looping, assuming checkFunction is something you define to handle the coordinate checks.

You can use vanilla JS to loop like this:

for (var i in myArray) {
   checkFunction(myArray[i]);
}

Or you can use JQuery to loop like this:

$(myArray).each(function(index, value) {
    checkFunction(value);
});

4 Comments

We have to use for...of to handle iterating through arrays, while for...in handles the properties of an object.
No? I'm not saying for...of won't work, but I will say that for...in does work. I use it daily. jsfiddle.net/9hL42cuk
You're right, I shouldn't say we 'have to' do anything of the sort. Most of the time, looping over the enumerable properties of an array is the same as looping over its iterable properties. It just requires a few reasonable assumptions (like that your array won't have any undefined keys, no one will try to use destructuring in the loop, and Array.prototype doesn't have any custom properties in the current scope.) It's recommended to use for...of for the sake of weird-proofing.
Now that I never knew, but I'm also pretty strict on how I structure the data (i.e. not nesting things weirdly). I mostly work with API's I've written myself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.