Artsy
Artsy

Reputation: 1

Placing Geolocated Coordinates in a jQuery File

I am having difficulty inserting the geolocated coordinates (latitude and longitude) of the current user's location into a PHP/MySQL generated xml file. It requires the user's geolocation to correctly generate the 20 closest businesses within a 30-mile radius. I am currently using a jQuery-powered store locator script to generate the map. The script works fine with a static URL as the xmlLocation, but when I try to use variables in the URL it just outputs an undefined alert message. My aim is to get javascript to place the latitude and longitude values of the user's location into the PHP GET variables so that the XML generator can generate correct output. It looks like this:

LocationGlobal = 'data/gen_default_map.php?lat=' + lat + '&lng=' + lon + '&radius=30';

And should ouput something like this:

data/gen_default_map.php?lat=34.383747&lng=-82.364574&radius=30

I have made modifications to the script and placed comments accordingly. You probably only need to concern yourself with the first 42 lines of the code, but just in case here is the script in it's entirety:

/* Get the User's Current Location and place it in the URL */   
/*--------------------------------------------------*/

var LocationGlobal;

if(navigator.geolocation)
{
    navigator.geolocation.getCurrentPosition(function(position)
{
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
    LocationGlobal = 'data/gen_default_map.php?lat=' + lat + '&lng=' + lon + '&radius=30';
    alert(LocationGlobal); // Sets correctly here
    return LocationGlobal;
    });
} else {
    console.log('Error getting coordinates.');  
}

alert(LocationGlobal); // Undefined here
/*--------------------------------------------------*/

(function ($) {
$.fn.storeLocator = function (options) {

    var settings = $.extend({
        'mapDiv': 'map',
        'listDiv': 'list',
        'formID': 'user-location',
        'pinColor': 'fe7569',
        'startPinColor': '66bd4a',
        'pinTextColor': '000000',
        'storeLimit': 10,
        'distanceAlert': 60,
        'xmlLocation': LocationGlobal, //'data/gen_default_map.php?lat=34&lng=-82&radius=30', <--- the commented static URL works but variable doesn't
        'addressErrorMsg': 'Please enter valid address address or postcode',
        'googleDistanceMatrixDestinationLimit': 25,
        'defaultLat': 34.8483680,
        'defaultLng': -82.400440,
        'defaultLocationName': 'Greenville, South Carolina'
    }, options);

    return this.each(function () {
        var $this = $(this);

        // global array of shop objects
        var _locationset = new Array();
        var geocoder;

        // Calculate distances from passed in origin to all locations in the [_locationset] array
        // using Google Maps Distance Matrix Service https://developers.google.com/maps/documentation/javascript/reference#DistanceMatrixService
        var GeoCodeCalc = {};
        GeoCodeCalc.CalcDistanceGoogle = function (origin, callback) {
            var destCoordArr = new Array();
            var subFunctionTokens = [];

            $.each(_locationset, function (ix, loc) {
                destCoordArr.push(loc.LatLng);
            });

            for (var i = 0; i < destCoordArr.length; i = i + settings.googleDistanceMatrixDestinationLimit) { // Google Distance Matrix allows up to 25 destinations to be passed in
                var tempArr = destCoordArr.slice(i, Math.min(i + settings.googleDistanceMatrixDestinationLimit));
                subFunctionTokens.push(this.CallGoogleDistanceMatrix(i, origin, tempArr));
            }

            $.when.apply($, subFunctionTokens)
                  .then(function () {
                      callback(true);
                  });
        };

        GeoCodeCalc.CallGoogleDistanceMatrix = function (startIndex, origin, destinations) {
            var token = $.Deferred();
            var service = new google.maps.DistanceMatrixService();
            service.getDistanceMatrix(
              {
                  origins: [origin],
                  destinations: destinations,
                  travelMode: google.maps.TravelMode.DRIVING,
                  unitSystem: google.maps.UnitSystem.IMPERIAL
              }, function (response, status) {
                  if (response && response.rows.length) {
                      var results = response.rows[0].elements;
                      $.each(results, function (j, val) {
                          if (results[j].status != "ZERO_RESULTS") {
                              _locationset[startIndex + j].Distance = GoogleMapDistanceTextToNumber(results[j].distance.text);
                          }
                      });

                      token.resolve();
                  }
              });

            return token.promise();
        };

        // Converts "123.45 mi" into 123.45
        function GoogleMapDistanceTextToNumber(str) {
            return Number(str.replace(/[^0-9.]/g, ""));
        }

        // removes Google Maps URL unfriendly chars from a string
        function formatGoogleMapUrlString(str) {
            return str.replace("&", "%26").replace(" ", "+");
        }

        //Geocode function for the origin location
        geocoder = new google.maps.Geocoder();
        function GoogleGeocode() {
            this.geocode = function (address, callbackFunction) {
                geocoder.geocode({ 'address': address }, function (results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        var result = {};
                        result.latitude = results[0].geometry.location.lat();
                        result.longitude = results[0].geometry.location.lng();
                        result.formatted_address = results[0].formatted_address;
                        result.address_components = results[0].address_components;
                        callbackFunction(result);
                    } else {
                        handleError("Geocode was not successful for the following reason: " + status);
                        callbackFunction(null);
                    }
                });
            };

            this.geocodeLatLng = function (LatLng, callbackFunction) {
                geocoder.geocode({ 'location': LatLng }, function (results, status) {
                    if (status == google.maps.GeocoderStatus.OK && results.length) {
                        callbackFunction(results[0]);
                    } else {
                        handleError("Geocode was not successful for the following reason: " + status);
                        callbackFunction(null);
                    }
                });
            };
        }

        //Process form input
        $(function () {
            $(document).on('submit', '#' + settings.formID, function (e) {
                $("#lblError").html("");
                //Stop the form submission
                e.preventDefault();
                //Get the user input and use it
                var userinput = $('form').serialize();
                userinput = userinput.replace("address=", "");
                if (userinput == "") {
                    handleError(settings.addressErrorMsg);
                }

                var g = new GoogleGeocode();
                var address = userinput;
                g.geocode(address, function (data) {
                    if (data != null) {
                        showAddress(data);
                        mapping(data.latitude, data.longitude);
                    } else {
                        //Unable to geocode
                        handleError(settings.addressErrorMsg);
                    }
                });

                //Replace spaces in user input
                userinput = formatGoogleMapUrlString(userinput);
            });
        });

        $(document).ready(function () {
            // Try HTML5 geolocation
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function (position) {
                    //map.setCenter(pos);
                    var g = new GoogleGeocode();
                    var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

                    g.geocodeLatLng(latlng, function (address) {
                        if (address) {
                            showAddress(address);
                        } else {
                            //Unable to geocode
                            handleNoGeolocation('Error: Unable to geocode address');
                        }
                    });

                    // do the mapping stuff
                    mapping(position.coords.latitude, position.coords.longitude);

                }, function () {
                    handleNoGeolocation("Tracking of location was not allowed.");
                });
            } else {
                // Browser doesn't support Geolocation
                handleNoGeolocation(false);
            }
        });

        function showAddress(address) {
            $("#lblAddress").html(address.formatted_address);
            // find a postcode and show it in the address textbox
            $.each(address.address_components, function (i, val) {
                if (val.types[0] == "postal_code") {
                    $("#address").val(val.short_name);
                    return false; // breaks the each() loop
                }
            });
        }

        function handleNoGeolocation(error) {
            if (error) {
                var content = error;
            } else {
                var content = 'Error: Your browser doesn\'t support geolocation.';
            }

            handleError(content + " Using default location.");
            mapping(settings.defaultLat, settings.defaultLng);
            $("#lblAddress").html(settings.defaultLocationName);

        }

        function handleError(error) {
            $("#lblError").html(error);
        }

        //Now all the mapping stuff
        function mapping(orig_lat, orig_lng) {
            $(function () {
                //Parse xml with jQuery
                $.ajax({
                    type: "GET",
                    url: settings.xmlLocation,
                    dataType: "xml",
                    success: function (xml) {
                        _locationset = new Array();
                        $(xml).find('Placemark').each(function (i) {
                            var shop = {
                                Name: $(this).find('name').text(),
                                //Take the lat lng from the user, geocoded above
                                LatLng: new google.maps.LatLng(
                                    $(this).find('coordinates').text().split(",")[1],
                                    $(this).find('coordinates').text().split(",")[0]),
                                Description: $(this).find('description').text(),
                                Marker: null,
                                Distance: null
                            };
                            _locationset.push(shop);
                        });

                        // Calc Distances from user's location
                        GeoCodeCalc.CalcDistanceGoogle(new google.maps.LatLng(orig_lat, orig_lng), function (success) {
                            if (!success) { //something went wrong
                                handleError("Unable to calculate distances at this time");
                            }
                            else {
                                //Sort the multi-dimensional array numerically
                                _locationset.sort(function (a, b) {
                                    return ((a.Distance < b.Distance) ? -1 : ((a.Distance > b.Distance) ? 1 : 0));
                                });

                                // take "N" closest shops
                                _locationset = _locationset.slice(0, settings.storeLimit);

                                //Check the closest marker
                                if (_locationset[0].Distance > settings.distanceAlert) {
                                    handleError("Unfortunately, our closest location is more than " + settings.distanceAlert + " miles away.");
                                }

                                //Create the map with jQuery
                                $(function () {
                                    var orig_LatLng = new google.maps.LatLng(orig_lat, orig_lng);
                                    //Google maps settings
                                    var myOptions = {
                                        center: orig_LatLng,
                                        mapTypeId: google.maps.MapTypeId.ROADMAP
                                    };

                                    var map = new google.maps.Map(document.getElementById(settings.mapDiv), myOptions);
                                    //Create one infowindow to fill later
                                    var infowindow = new google.maps.InfoWindow();

                                    //Add user location marker
                                    var marker = createUserMarker(orig_LatLng, "0", settings.startPinColor);
                                    marker.setAnimation(google.maps.Animation.DROP);
                                    var bounds = new google.maps.LatLngBounds();
                                    bounds.extend(orig_LatLng);

                                    $("#" + settings.listDiv).empty();

                                    $(_locationset).each(function (i, location) {
                                        bounds.extend(location.LatLng);
                                        letter = String.fromCharCode("A".charCodeAt(0) + i);
                                        location.Marker = createMarker(location.LatLng, letter, settings.pinColor);
                                        create_infowindow(location);
                                        listClick(letter, location);
                                    });

                                    // zoom in/out to show all markers
                                    map.fitBounds(bounds);

                                    function listClick(letter, shop) {
                                        $('<li />').html("<div class=\"list-details\">"
                                        + "<div class=\"list-label\">" + letter + "<\/div><div class=\"list-content\">"
                                        + "<div class=\"loc-name\">" + shop.Name + "<\/div> <div class=\"loc-addr\">" + shop.Description + "<\/div>"
                                        + (shop.Distance ? "<div class=\"loc-addr2\"><i>approx. " + shop.Distance + " " + ((shop.Distance == 1) ? "mile" : "miles" ) + "</i><\/div>" : "")
                                        + "<div class=\"loc-web\"><a href=\"http://maps.google.co.uk/maps?saddr="
                                        + formatGoogleMapUrlString($("#address").val()) + "+%40" + orig_lat + "," + orig_lng
                                        + "&daddr=" + formatGoogleMapUrlString(shop.Name) + "+%40" + shop.LatLng.lat() + "," + shop.LatLng.lng()
                                        + "&hl=en" + "\" target=\"_blank\">&raquo; Get directions</a><\/div><\/div><\/div>")
                                        .click(function () {
                                            create_infowindow(shop, "left");
                                        }).appendTo("#" + settings.listDiv);
                                    };

                                    //Custom marker function - aplhabetical
                                    function createMarker(point, letter, pinColor) {
                                        //Set up pin icon with the Google Charts API for all of our markers
                                        var pinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=" + letter + "|" + pinColor + "|" + settings.pinTextColor,
                                          new google.maps.Size(21, 34),
                                          new google.maps.Point(0, 0),
                                          new google.maps.Point(10, 34));
                                        var pinShadow = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_shadow",
                                          new google.maps.Size(40, 37),
                                          new google.maps.Point(0, 0),
                                          new google.maps.Point(12, 35));

                                        //Create the markers
                                        return new google.maps.Marker({
                                            position: point,
                                            map: map,
                                            icon: pinImage,
                                            shadow: pinShadow,
                                            draggable: false
                                        });
                                    };

                                    //Custom marker function - aplhabetical
                                    function createUserMarker(point, letter, pinColor) {
                                        //Set up pin icon with the Google Charts API for all of our markers
                                        var pinImage = new google.maps.MarkerImage("images/green_pin.png");

                                        //Create the markers
                                        return new google.maps.Marker({
                                            position: point,
                                            map: map,
                                            title: "Your Location",
                                            icon: pinImage,
                                            draggable: false
                                        });
                                    };

                                    //Infowindows
                                    function create_infowindow(shop, listLocation) {

                                        //Is the distance more than one mile?
                                        if (shop.Distance == 1) {
                                            var mi_s = "mile";
                                        } else {
                                            var mi_s = "miles";
                                        }

                                        var formattedAddress = "<div class=\"infoWindow\"><b>" + shop.Name + "<\/b>"
                                        + "<div>" + shop.Description + "<\/div>"
                                        + (shop.Distance ? "<div><i>" + shop.Distance + " " + mi_s + "<\/i><\/div><\/div>" : "<\/div>");

                                        //Opens the infowindow when list item is clicked
                                        if (listLocation == "left") {
                                            infowindow.setContent(formattedAddress);
                                            infowindow.open(shop.Marker.get(settings.mapDiv), shop.Marker);
                                        }
                                        //Opens the infowindow when the marker is clicked
                                        else {
                                            google.maps.event.addListener(shop.Marker, 'click', function () {
                                                infowindow.setContent(formattedAddress);
                                                infowindow.open(shop.Marker.get(settings.mapDiv), shop.Marker);
                                            })
                                        }
                                    };
                                });
                            }
                        });
                    }
                });
            });
        }

    });
};
})(jQuery);

Under var settings I need xmlLocation to be the dynamically geolocated URL. It seems the variable is not being set correctly. I get an undefined error message when I try to call LocationGlobal. I have speculated on this issue and have hit a dead end with it. Any help is greatly appreciated. Thanks.

Upvotes: 0

Views: 1425

Answers (1)

shakib
shakib

Reputation: 5469

The alert shows undefined because of the callback nature of the getCurrentLocation() operation. You have to call the LocationGlobal dependent function from inside the callback function of the getCurrentLocation() operation. probably like,

navigator.geolocation.getCurrentPosition(function(position)
{
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
    LocationGlobal = 'data/gen_default_map.php?lat=' + lat + '&lng=' + lon + '&radius=30';
    alert(LocationGlobal);
    $('#map').storeLocaor({ mapDiv: 'map', xmlLocation: LocationGlobal  }); //Just an example
});

hope this helps.

Upvotes: 0

Related Questions