0

I know this can't be done exactly how I have said in the title but I'm really not sure what to do the achieve the required results.

Here is the code:

var map;

// Filters
var filterArray = [
    {filter: 'school', icon: 'assets/img/mapMarkerIcos-schools.png', markersArray: 'schoolMarkers'},
    {filter: 'restaurant', icon: 'assets/img/mapMarkerIcos-restaurants.png', markersArray: 'restaurantMarkers'},
    {filter: 'subway_station', icon: 'assets/img/mapMarkerIcos-stations.png', markersArray: 'stationMarkers'},
    {filter: 'convenience_store', icon: 'assets/img/mapMarkerIcos-shops.png', markersArray: 'shopMarkers'}
];
var schoolMarkers = [];
var restaurantMarkers = [];
var stationMarkers = [];
var shopMarkers = [];

//console.log(filterArray);

// Map center coordinates
var coords = [
    parseFloat(document.getElementById('mapLatitude').value),
    parseFloat(document.getElementById('mapLongitude').value)
];
var area = new google.maps.LatLng(coords[0], coords[1]);
var filter = document.getElementById('amenityType').value;

// Add marker function
function addMarker(props) {
    var marker = new google.maps.Marker({
        position: props.geometry.location,
        title: props.name,
        address: props.vicinity,
        animation: google.maps.Animation.DROP,
        map:map
    });
    // Set icon if it exists
    if(props.icon) {
        var icon = document.getElementById('markerIcon').value;
        marker.setIcon(icon);
    }
    // Create info window when clicked
    var contentString = '<h3>' + props.name +'</h3><span>' + props.vicinity + '</span>';
    var infoWindow = new google.maps.InfoWindow({
        content: contentString
    });
    marker.addListener('click', function() {
        infoWindow.open(map, marker);
    });
    google.maps.event.addListener(map, 'click', function() {
        infoWindow.close();
    });
}

// When the window has finished loading create our google map below
google.maps.event.addDomListener(window, 'load', init);

function init() {
  
    // Basic options for a simple Google Map
    // For more options see: https://developers.google.com/maps/documentation/javascript/reference#MapOptions
    var mapOptions = {
        // How zoomed in you want the map to start at (always required)
        zoom: 14,

        // The latitude and longitude to center the map (always required)
        center: area,


        // How you would like to style the map. 
        // This is where you would paste any style found on Snazzy Maps.
        styles: [{"featureType":"water","elementType":"geometry","stylers":[{"color":"#e9e9e9"},{"lightness":17}]},{"featureType":"landscape","elementType":"geometry","stylers":[{"color":"#f5f5f5"},{"lightness":20}]},{"featureType":"road.highway","elementType":"geometry.fill","stylers":[{"color":"#ffffff"},{"lightness":17}]},{"featureType":"road.highway","elementType":"geometry.stroke","stylers":[{"color":"#ffffff"},{"lightness":29},{"weight":0.2}]},{"featureType":"road.arterial","elementType":"geometry","stylers":[{"color":"#ffffff"},{"lightness":18}]},{"featureType":"road.local","elementType":"geometry","stylers":[{"color":"#ffffff"},{"lightness":16}]},{"featureType":"poi","elementType":"geometry","stylers":[{"color":"#f5f5f5"},{"lightness":21}]},{"featureType":"poi.park","elementType":"geometry","stylers":[{"color":"#dedede"},{"lightness":21}]},{"elementType":"labels.text.stroke","stylers":[{"visibility":"on"},{"color":"#ffffff"},{"lightness":16}]},{"elementType":"labels.text.fill","stylers":[{"saturation":36},{"color":"#333333"},{"lightness":40}]},{"elementType":"labels.icon","stylers":[{"visibility":"on"},{"color":"#eeeeee"},{"lightness":50}]},{"featureType":"transit","elementType":"geometry","stylers":[{"color":"#f2f2f2"},{"lightness":19}]},{"featureType":"administrative","elementType":"geometry.fill","stylers":[{"color":"#fefefe"},{"lightness":20}]},{"featureType":"administrative","elementType":"geometry.stroke","stylers":[{"color":"#fefefe"},{"lightness":17},{"weight":1.2}]}]
    };

    // Get the HTML DOM element that will contain your map 
    // We are using a div with id="map" seen below in the <body>
    var mapElement = document.getElementById('map');

    // Create the Google Map using our element and options defined above
    map = new google.maps.Map(mapElement, mapOptions);

    // Request nearby amenities for every Filter, then store this in an array each
    for (i = 0; i < filterArray.length; i++) {
        var filterObj = filterArray[i];
        var filter = filterObj.filter;
        console.log(filter);
        var markersArray = filterObj.markersArray;
        console.log(markersArray);
        var request = {
            location: area,
            radius: '2000',
            fields: ['name', 'geometry'],
            type: [filter]
        };
        service = new google.maps.places.PlacesService(map);
        service.nearbySearch(request, callback);
        //var markersArray = this.markersArray;
    }

    // Add results to Array
    function callback(results, status) {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
            //console.log(results);
            console.log('results found');
            //markersArray.push(results);
            /*
            for (var i = 0; i < results.length; i++) {
                //console.log(results[i]);
                addMarker(results[i]);
            }
            */
        }
    }

}
html, body {
    margin: 0;
}
#map {
    height: 400px;
    width: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Interactive Map</title>
    <link rel="stylesheet" href="assets/css/style.css">
</head>
<body>

    <input id="mapLatitude" type="hidden" value="51.571527">
    <input id="mapLongitude" type="hidden" value="-0.149113">
    <input id="amenityType" type="hidden" value="school">
    <input id="markerIcon" type="hidden" value="assets/img/mapMarkerIcos-schools.png">
    
    <div id="map"></div>

    <button class="mapFilter" data-filter="school">schools</button><br>
    <button class="mapFilter" data-filter="restaurant">restaurants</button><br>
    <button class="mapFilter" data-filter="subway_station">stations</button><br>
    <button class="mapFilter" data-filter="convenience_store">shops</button><br>

    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBNPO77AnQOdXcUhisHtfu_RP0Ha3bZKn8&libraries=places"></script>
    <script src="assets/js/main.js"></script>
    
</body>
</html>

The problem is that I just don't see a way to pass the markersArray to the callback so that I will be able to push the results to the relevant array.

The issue is comment '// Request nearby amenities for every Filter, then store this in an array each'

and the callback at comment '// Add results to Array'

I have tried so many different things now and I'm just at a loss.

Thank you.

Edit: The required results are that I loop 4 times and get 4 lots of results. I need to push these 4 lots of results into 4 seperate arrays.

Carl Piper
  • 81
  • 2
  • 9
  • Put the `callback` declaration inside the loop body to make it a closure over `markersArray` (but [fix the scope](https://stackoverflow.com/q/750486/1048572) by using an IIFE or `let` declarations). – Bergi Feb 21 '19 at 13:55

2 Answers2

1

You can use an IIFE instead of passing the callback function reference directly. The IIFE receives makersArray as argument and returns a function which will be the callback but in its body, arguments passed to the invocation of the IIFE are available.

  for (i = 0; i < filterArray.length; i++) {

    //...

    service.nearbySearch(request, ((markersArray, counter) => 
      (results, status) => {
         // makersArray is available here
         // use results[counter] ...
      }
    )(markersArray, i));

  }

Edit: makersArray => markersArray

Update: Because you call an async function (service.nearbySearch) in a for loop, you also need to pass the loop counter into the IIFE. In this example, use counter instead if i inside the callback.

marekful
  • 14,986
  • 6
  • 37
  • 59
  • Thank you for the quick reply it gets the variable as asked, there was a small typo in the last bit of your code but i fixed it on my end. When I log the markersArray to the console it repeats the last item in markersArray item 4 time instead of each item once. Do you know how I would fix this? – Carl Piper Feb 21 '19 at 12:49
  • Without seeing how exactly it's implemented now I can't tell, but you call `service.nearbySearch()` in a for loop multiple times. – marekful Feb 21 '19 at 12:55
  • Because `service.nearbySearch` is async, you also need to pass loop counter to the IIFE. See [this](https://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop) and the updated answer. – marekful Feb 21 '19 at 12:58
  • I've made a jsfiddle with my exact current code, I'm not sure why it's not showing anything there but the code works on my machine. you can see the output in the console if you run on your machine https://jsfiddle.net/6w0r21ea/4/ – Carl Piper Feb 21 '19 at 15:05
  • It's hard to see what the goal is in this code. You ask `what to do the achieve the required results`, please explain what exactly is required. – marekful Feb 21 '19 at 15:20
  • I'll try to explain as best I can thank you for your patience. The loop makes 4 requests with 4 lots of results. I need to push those results to 4 separate arrays – Carl Piper Feb 21 '19 at 15:23
  • I have made an updated jsfiddle which logs the 4 results to the console. https://jsfiddle.net/zaxb56hd/ – Carl Piper Feb 21 '19 at 15:51
  • Thank you that does exactly what I need but for some reason when I copy the js into my site it doesn't work as it does in the jsfiddle. It duplicates all markers and it doesn't show as an object it shows up weird in the console. Do you have any idea why this could be? – Carl Piper Feb 21 '19 at 17:01
  • Remove `init()` from the bottom. I added it there as jsfiddle won't call the window.onload... – marekful Feb 21 '19 at 17:03
  • Perfect Thank you for your help, Now i need to work out the next part :/ – Carl Piper Feb 21 '19 at 17:08
0

There is another way to retrive the markersArray from the caller which I ovserved from debugging your code. But I am not sure how you are going to add markersArray to show on your map. Here is my observation, please post your working code when you are done, will need help to understand this.

GIT Repo: https://github.com/helloritesh000/how-to-pass-variable-to-my-callback-function-or-similar

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Interactive Map</title>
    <link rel="stylesheet" href="assets/css/style.css">
    <style>
        html, body {
        margin: 0;
        }
        #map {
            height: 400px;
            width: 100%;
        }
    </style>
</head>
<body>

    <input id="mapLatitude" type="hidden" value="51.571527">
    <input id="mapLongitude" type="hidden" value="-0.149113">
    <input id="amenityType" type="hidden" value="school">
    <input id="markerIcon" type="hidden" value="assets/img/mapMarkerIcos-schools.png">

    <div id="map"></div>

    <button class="mapFilter" data-filter="school">schools</button><br>
    <button class="mapFilter" data-filter="restaurant">restaurants</button><br>
    <button class="mapFilter" data-filter="subway_station">stations</button><br>
    <button class="mapFilter" data-filter="convenience_store">shops</button><br>

    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBNPO77AnQOdXcUhisHtfu_RP0Ha3bZKn8&libraries=places"></script>
    <script src="assets/js/main.js"></script>


    <script type="text/javascript">
        var map;

// Filters
var filterArray = [
    {filter: 'school', icon: 'assets/img/mapMarkerIcos-schools.png', markersArray: 'schoolMarkers'},
    {filter: 'restaurant', icon: 'assets/img/mapMarkerIcos-restaurants.png', markersArray: 'restaurantMarkers'},
    {filter: 'subway_station', icon: 'assets/img/mapMarkerIcos-stations.png', markersArray: 'stationMarkers'},
    {filter: 'convenience_store', icon: 'assets/img/mapMarkerIcos-shops.png', markersArray: 'shopMarkers'}
];
var schoolMarkers = [];
var restaurantMarkers = [];
var stationMarkers = [];
var shopMarkers = [];

//console.log(filterArray);

// Map center coordinates
var coords = [
    parseFloat(document.getElementById('mapLatitude').value),
    parseFloat(document.getElementById('mapLongitude').value)
];
var area = new google.maps.LatLng(coords[0], coords[1]);
var filter = document.getElementById('amenityType').value;

// Add marker function
function addMarker(props) {
    var marker = new google.maps.Marker({
        position: props.geometry.location,
        title: props.name,
        address: props.vicinity,
        animation: google.maps.Animation.DROP,
        map:map
    });
    // Set icon if it exists
    if(props.icon) {
        var icon = document.getElementById('markerIcon').value;
        marker.setIcon(icon);
    }
    // Create info window when clicked
    var contentString = '<h3>' + props.name +'</h3><span>' + props.vicinity + '</span>';
    var infoWindow = new google.maps.InfoWindow({
        content: contentString
    });
    marker.addListener('click', function() {
        infoWindow.open(map, marker);
    });
    google.maps.event.addListener(map, 'click', function() {
        infoWindow.close();
    });
}

// When the window has finished loading create our google map below
google.maps.event.addDomListener(window, 'load', init);

function init() {
    var markersArray = null;
    // Basic options for a simple Google Map
    // For more options see: https://developers.google.com/maps/documentation/javascript/reference#MapOptions
    var mapOptions = {
        // How zoomed in you want the map to start at (always required)
        zoom: 14,

        // The latitude and longitude to center the map (always required)
        center: area,


        // How you would like to style the map. 
        // This is where you would paste any style found on Snazzy Maps.
        styles: [{"featureType":"water","elementType":"geometry","stylers":[{"color":"#e9e9e9"},{"lightness":17}]},{"featureType":"landscape","elementType":"geometry","stylers":[{"color":"#f5f5f5"},{"lightness":20}]},{"featureType":"road.highway","elementType":"geometry.fill","stylers":[{"color":"#ffffff"},{"lightness":17}]},{"featureType":"road.highway","elementType":"geometry.stroke","stylers":[{"color":"#ffffff"},{"lightness":29},{"weight":0.2}]},{"featureType":"road.arterial","elementType":"geometry","stylers":[{"color":"#ffffff"},{"lightness":18}]},{"featureType":"road.local","elementType":"geometry","stylers":[{"color":"#ffffff"},{"lightness":16}]},{"featureType":"poi","elementType":"geometry","stylers":[{"color":"#f5f5f5"},{"lightness":21}]},{"featureType":"poi.park","elementType":"geometry","stylers":[{"color":"#dedede"},{"lightness":21}]},{"elementType":"labels.text.stroke","stylers":[{"visibility":"on"},{"color":"#ffffff"},{"lightness":16}]},{"elementType":"labels.text.fill","stylers":[{"saturation":36},{"color":"#333333"},{"lightness":40}]},{"elementType":"labels.icon","stylers":[{"visibility":"on"},{"color":"#eeeeee"},{"lightness":50}]},{"featureType":"transit","elementType":"geometry","stylers":[{"color":"#f2f2f2"},{"lightness":19}]},{"featureType":"administrative","elementType":"geometry.fill","stylers":[{"color":"#fefefe"},{"lightness":20}]},{"featureType":"administrative","elementType":"geometry.stroke","stylers":[{"color":"#fefefe"},{"lightness":17},{"weight":1.2}]}]
    };

    // Get the HTML DOM element that will contain your map 
    // We are using a div with id="map" seen below in the <body>
    var mapElement = document.getElementById('map');

    // Create the Google Map using our element and options defined above
    map = new google.maps.Map(mapElement, mapOptions);

    // Request nearby amenities for every Filter, then store this in an array each
    for (i = 0; i < filterArray.length; i++) {
        var filterObj = filterArray[i];
        var filter = filterObj.filter;
        console.log(filter);
        markersArray = filterObj.markersArray;
        console.log(markersArray);
        var request = {
            location: area,
            radius: '2000',
            fields: ['name', 'geometry'],
            type: [filter]
        };
        service = new google.maps.places.PlacesService(map);
        service.nearbySearch(request, callback, markersArray);
        //var markersArray = this.markersArray;
        <!-- service.nearbySearch(request, ((markersArray) =>  -->
          <!-- (result, status) => { -->
             <!-- // makersArray is available here -->
          <!-- } -->
        <!-- )(makersArray)); -->
        //
    }

    // Add results to Array
    function callback(results, status) {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
        var args = arguments[2];
        var schoolList = arguments[2].j.caller.arguments[2].results;
            //console.log(results);
            console.log('results found');
            //markersArray.push(results);

            //for (var i = 0; i < results.length; i++) {
                //console.log(results[i]);
                //addMarker(results[i]);
            //}

        }
    }

}


    </script>
</body>
</html>
Ritesh Kumar
  • 114
  • 6